127 lines
3.4 KiB
Markdown
127 lines
3.4 KiB
Markdown
# pyMCPBroker
|
|
|
|
Small FastAPI broker exposing three stable meta-tools over MCP `stdio` sources:
|
|
|
|
- `meta_tree`
|
|
- `meta_desc`
|
|
- `meta_call`
|
|
|
|
The broker does not expose raw MCP tools directly. A model first discovers paths with `meta_tree`, inspects a leaf with `meta_desc`, then executes it with `meta_call`.
|
|
|
|
## What is implemented
|
|
|
|
- MCP `stdio` sources only
|
|
- persistent subprocess per unique source command
|
|
- `initialize`, `notifications/initialized`, `tools/list`, `tools/call`
|
|
- source-side tool auto-discovery
|
|
- optional allow/deny glob filters
|
|
- optional tool overrides
|
|
- optional path aliases
|
|
- broker-side JSON Schema validation
|
|
- structured errors
|
|
- compact result truncation
|
|
- optional shared secret
|
|
|
|
## Install
|
|
|
|
```bash
|
|
pip install .
|
|
```
|
|
|
|
## Run
|
|
|
|
```bash
|
|
python -m pyMCPBroker 0.0.0.0:8100 /config.json
|
|
```
|
|
|
|
Optional shared secret:
|
|
|
|
```bash
|
|
python -m pyMCPBroker 0.0.0.0:8100 /config.json mysecret
|
|
```
|
|
|
|
## Config model
|
|
|
|
User-facing config is tree-first. You mount a real source inline on a node with `source`. The broker discovers its tools automatically and exposes them as child leaves of that node.
|
|
|
|
A declared root node is optional. If `tree` is a list, `/` is created implicitly.
|
|
|
|
Example:
|
|
|
|
```json
|
|
{
|
|
"tree": [
|
|
{
|
|
"path": "/repo",
|
|
"type": "node",
|
|
"summary": "Repository operations",
|
|
"children": [
|
|
{
|
|
"path": "/repo/read",
|
|
"type": "node",
|
|
"summary": "Read repository data",
|
|
"source": {
|
|
"backend": "stdio",
|
|
"command": "/opt/gitea-mcp/gitea-mcp --host ${GITEA_URL} --token ${GITEA_TOKEN}",
|
|
"tool_filter": ["get_*", "list_*", "search_*", "!delete_*", "!create_*"],
|
|
"path_aliases": {
|
|
"get_file_contents": "get_file"
|
|
},
|
|
"tool_overrides": {
|
|
"get_file_contents": {
|
|
"summary": "Read one file from a repository",
|
|
"max_output_chars": 12000,
|
|
"example_args": {
|
|
"owner": "myorg",
|
|
"repo": "demo-repo",
|
|
"ref": "main",
|
|
"filePath": "README.md"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
With that config, the broker auto-exposes paths such as:
|
|
|
|
- `/repo/read/get_file`
|
|
- `/repo/read/list_branches`
|
|
- `/repo/read/search_code`
|
|
|
|
depending on what the mounted MCP source actually reports through `tools/list`.
|
|
|
|
## Notes
|
|
|
|
- `tool_filter` is optional. If omitted, all tools from the source are exposed.
|
|
- `tool_overrides` is optional.
|
|
- filter semantics are unordered:
|
|
- positive patterns allow
|
|
- `!pattern` denies
|
|
- if there is no positive pattern, all tools are allowed first, then deny rules are applied
|
|
- `path_aliases` only renames exposed leaf names; it does not change the real MCP tool name.
|
|
|
|
## Files
|
|
|
|
- `docs/SPEC.md`: user-facing spec for the implemented behavior
|
|
- `examples/config.example.json`: example config
|
|
|
|
|
|
## VS Code
|
|
|
|
The repository includes a minimal `.vscode/` setup for running and debugging pytest and for launching the broker with `smoke_config.json`.
|
|
|
|
|
|
## OpenAPI guidance for agents
|
|
|
|
The FastAPI/OpenAPI descriptions are intentionally directive. The broker hides business tools behind three stable entry tools, so agents should start with `meta_tree`, inspect with `meta_desc`, then execute with `meta_call`.
|
|
|
|
|
|
## 0.2.3
|
|
|
|
- Prefer MCP tool descriptions over raw tool names when building child summaries in `meta_tree`.
|