fabro/lib/crates/fabro-mcp/tests/test_mcp_server.py
Bryan Helmkamp 28884ae093 rename Arc to Fabro in all Rust crates, symbols, env vars, and supporting files
- Rename 20 crate directories lib/crates/arc-* → fabro-*
- Update all Cargo.toml: crate names, dep paths, feature flags, bin name
- Rename arc_server module → fabro_server in fabro-llm
- ArcError → FabroError across 30+ files
- ARC_VERSION/ARC_GIT_SHA/ARC_BUILD_DATE → FABRO_* constants
- All use/qualified paths: arc_agent:: → fabro_agent::, etc. (~1500 occurrences)
- Env vars ARC_* → FABRO_* in string literals and shell scripts
- String literals: X-Arc-Demo, arc-bot, arc@local, arc-web, arc-mcp, etc.
- Path strings: .arc/ → .fabro/, arc.toml → fabro.toml, refs/arc/ → refs/fabro/
- arc-api.yaml → fabro-api.yaml (OpenAPI spec)
- skills/arc-create-workflow → fabro-create-workflow
- trycmd fixtures: $ arc → $ fabro
- Inline snapshots (insta) updated
- CI, Docker, install.sh, scripts, CLAUDE.md, AGENTS.md
- TypeScript app: env vars, headers, JWT issuer
- Docs: page slugs, git refs, config paths, sandbox names, repo URLs
- Repo references: brynary/arc → fabro-sh/fabro

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 12:25:58 -04:00

100 lines
2.4 KiB
Python

#!/usr/bin/env python3
"""Minimal MCP server for integration testing over stdio.
Speaks JSON-RPC 2.0 over stdin/stdout per the MCP specification.
Exposes a single tool: echo(message) -> message.
"""
import json
import sys
SERVER_INFO = {
"name": "test-echo-server",
"version": "0.1.0",
}
TOOL = {
"name": "echo",
"description": "Echo back the message",
"inputSchema": {
"type": "object",
"properties": {
"message": {"type": "string", "description": "Message to echo"}
},
"required": ["message"],
},
}
def handle_request(req):
method = req.get("method")
req_id = req.get("id")
params = req.get("params", {})
if method == "initialize":
return {
"jsonrpc": "2.0",
"id": req_id,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {"tools": {}},
"serverInfo": SERVER_INFO,
},
}
if method == "tools/list":
return {
"jsonrpc": "2.0",
"id": req_id,
"result": {"tools": [TOOL]},
}
if method == "tools/call":
tool_name = params.get("name")
arguments = params.get("arguments", {})
if tool_name == "echo":
msg = arguments.get("message", "")
return {
"jsonrpc": "2.0",
"id": req_id,
"result": {
"content": [{"type": "text", "text": msg}],
},
}
return {
"jsonrpc": "2.0",
"id": req_id,
"result": {
"content": [{"type": "text", "text": f"unknown tool: {tool_name}"}],
"isError": True,
},
}
# Notifications (no id) — just ignore
if req_id is None:
return None
return {
"jsonrpc": "2.0",
"id": req_id,
"error": {"code": -32601, "message": f"Method not found: {method}"},
}
def main():
for line in sys.stdin:
line = line.strip()
if not line:
continue
try:
req = json.loads(line)
except json.JSONDecodeError:
continue
resp = handle_request(req)
if resp is not None:
sys.stdout.write(json.dumps(resp) + "\n")
sys.stdout.flush()
if __name__ == "__main__":
main()