Summary
MCP tool descriptions are static strings that never change regardless of which graph the user is connected to. This spec proposes a ToolContext system that enriches tool descriptions based on the connected graph's manifest and schema — making tools aware of shared repository context (SEC, sibling subgraphs), schema patterns (RoboLedger financial schema), and graph-specific guidance. Configuration lives in adapter manifests (adapters/sec/manifest.py) and schema extensions (schemas/extensions/roboledger.py).
Status
Draft
Problem Statement: Current State
Tool descriptions are hardcoded strings in get_tool_definition() on each tool class (middleware/mcp/tools/*.py). The only context-awareness today is:
describe-graph-structure has a hardcoded if self.client.graph_id in ("sec", "sec_historical") branch
get-example-queries has a hardcoded if self.client.graph_id == "sec" branch
_should_include_element_discovery() checks the manifest's has_element_discovery flag
Every other tool serves identical description text regardless of graph. This causes three problems:
- Discoverability —
sec_historical exists as a sibling subgraph but no tool description mentions it. An agent will never discover it unless they call list-workspaces.
- Schema mismatch — Tool descriptions reference SEC/XBRL patterns even for graphs with completely different schemas.
- Wasted context window — SEC-specific guidance (dimensional facts, period types) is served to every graph, wasting tokens.
Problem Statement: Desired State
Tool descriptions adapt to graph context:
- SEC graph: mentions
sec_historical sibling, includes dimensional fact warnings, period type guidance
- User graph with RoboLedger schema: references actual node types and relationships, omits SEC-specific cruft
- Custom user graph: gets clean generic descriptions with no financial schema references
Configuration is centralized:
- Shared repository MCP config lives in the adapter manifest (alongside billing, rate limits, endpoints)
- Schema-derived guidance lives in schema extension modules (alongside schema definitions)
- No hardcoded graph_id checks in tool classes
Problem Statement: Why Now?
v1.4.0 marks the platform maturation milestone. As we add more shared repositories and schema extensions, hardcoding if graph_id == "sec" branches doesn't scale. The sec_historical subgraph is already invisible to agents — this will only get worse as we add more subgraphs and shared repos.
Proposed Solution: Approach
Three new concepts:
-
MCPToolConfig — added to SharedRepositoryManifest in adapters/base.py. Contains tool_supplements (dict of tool_name → additional description text), sibling_subgraphs, and display_name.
-
MCP_GUIDANCE — a constant exported from schema extension modules (schemas/extensions/roboledger.py). Co-locates schema knowledge with the schema definition.
-
ToolContext — built at init time in GraphMCPTools from manifest + schema. Passed to each tool's get_tool_definition() to enrich descriptions.
Key design principle: append, not replace. Base descriptions are always present. Context supplements are added on top. User graphs with no manifest get today's generic descriptions (zero regression).
Components Affected
Other directories touched but not architecturally affected:
adapters/base.py — add MCPToolConfig dataclass
adapters/sec/manifest.py — add mcp_config field
schemas/extensions/roboledger.py — add MCP_GUIDANCE constant
Key Changes
middleware/mcp/tools/context.py — NEW: ToolContext dataclass
adapters/base.py — Add MCPToolConfig, add mcp_config to SharedRepositoryManifest
adapters/sec/manifest.py — Add mcp_config with tool supplements + sibling subgraphs
middleware/mcp/tools/base_tool.py — Update get_tool_definition() to accept ToolContext
middleware/mcp/tools/manager.py — Build ToolContext in __init__, pass to tools
middleware/mcp/tools/structure_tool.py — Remove hardcoded SEC branches (Phase 4)
middleware/mcp/tools/example_queries_tool.py — Remove hardcoded SEC branches (Phase 4)
middleware/mcp/tools/constants.py — Move schema-specific constants to schema guidance (Phase 4)
schemas/extensions/roboledger.py — Add MCP_GUIDANCE constant
middleware/mcp/tools/cypher_tool.py — Trim generic base description
Data Model Changes
No database schema changes. MCPToolConfig is a frozen dataclass on the manifest (in-memory config).
API Changes
No API contract changes. The /v1/graphs/{graph_id}/mcp/tools endpoint returns the same response shape — tool definitions with name, description, inputSchema. Only the description content changes based on graph context.
Implementation Plan
Dependencies: None — this is self-contained within the MCP tool layer.
Testing
Rollout
Environments: Development → Staging → Production
No feature flags needed — this only changes tool description text, not behavior. Descriptions are generated at tool-list time, so changes take effect immediately on deploy.
Rollback plan: Revert the PR. Tool descriptions go back to static strings.
Success Criteria
Open Questions
References
- Spec:
local/docs/specs/context-aware-mcp-tools.md
- Current tool implementations:
robosystems/middleware/mcp/tools/
- SEC manifest:
robosystems/adapters/sec/manifest.py
- Schema extensions:
robosystems/schemas/extensions/
- Shared repository registry:
robosystems/config/shared_repositories.py
Summary
MCP tool descriptions are static strings that never change regardless of which graph the user is connected to. This spec proposes a
ToolContextsystem that enriches tool descriptions based on the connected graph's manifest and schema — making tools aware of shared repository context (SEC, sibling subgraphs), schema patterns (RoboLedger financial schema), and graph-specific guidance. Configuration lives in adapter manifests (adapters/sec/manifest.py) and schema extensions (schemas/extensions/roboledger.py).Status
Draft
Problem Statement: Current State
Tool descriptions are hardcoded strings in
get_tool_definition()on each tool class (middleware/mcp/tools/*.py). The only context-awareness today is:describe-graph-structurehas a hardcodedif self.client.graph_id in ("sec", "sec_historical")branchget-example-querieshas a hardcodedif self.client.graph_id == "sec"branch_should_include_element_discovery()checks the manifest'shas_element_discoveryflagEvery other tool serves identical description text regardless of graph. This causes three problems:
sec_historicalexists as a sibling subgraph but no tool description mentions it. An agent will never discover it unless they calllist-workspaces.Problem Statement: Desired State
Tool descriptions adapt to graph context:
sec_historicalsibling, includes dimensional fact warnings, period type guidanceConfiguration is centralized:
Problem Statement: Why Now?
v1.4.0 marks the platform maturation milestone. As we add more shared repositories and schema extensions, hardcoding
if graph_id == "sec"branches doesn't scale. Thesec_historicalsubgraph is already invisible to agents — this will only get worse as we add more subgraphs and shared repos.Proposed Solution: Approach
Three new concepts:
MCPToolConfig— added toSharedRepositoryManifestinadapters/base.py. Containstool_supplements(dict of tool_name → additional description text),sibling_subgraphs, anddisplay_name.MCP_GUIDANCE— a constant exported from schema extension modules (schemas/extensions/roboledger.py). Co-locates schema knowledge with the schema definition.ToolContext— built at init time inGraphMCPToolsfrom manifest + schema. Passed to each tool'sget_tool_definition()to enrich descriptions.Key design principle: append, not replace. Base descriptions are always present. Context supplements are added on top. User graphs with no manifest get today's generic descriptions (zero regression).
Components Affected
/robosystems/middleware/)/robosystems/config/)Other directories touched but not architecturally affected:
adapters/base.py— addMCPToolConfigdataclassadapters/sec/manifest.py— addmcp_configfieldschemas/extensions/roboledger.py— addMCP_GUIDANCEconstantKey Changes
Data Model Changes
No database schema changes.
MCPToolConfigis a frozen dataclass on the manifest (in-memory config).API Changes
No API contract changes. The
/v1/graphs/{graph_id}/mcp/toolsendpoint returns the same response shape — tool definitions withname,description,inputSchema. Only thedescriptioncontent changes based on graph context.Implementation Plan
Phase 1: ToolContext and Manifest Config
middleware/mcp/tools/context.pywithToolContextdataclassMCPToolConfigtoadapters/base.pymcp_configto SEC manifestToolContextinGraphMCPTools.__init__get_tool_definition()Phase 2: Tool Description Enrichment
BaseTool.get_tool_definition()signaturePhase 3: Schema-Derived Guidance
MCP_GUIDANCEtoschemas/extensions/roboledger.pyPhase 4: Remove Hardcoded SEC Logic
if graph_id == "sec"branches from tool classesPERIOD_TYPE_GUIDANCEandDIMENSIONAL_FACTS_WARNINGto schema guidanceQUERY_PATTERN_GUIDANCEas shared constant (LadybugDB-specific, not schema-specific)Dependencies: None — this is self-contained within the MCP tool layer.
Testing
Rollout
Environments: Development → Staging → Production
No feature flags needed — this only changes tool description text, not behavior. Descriptions are generated at tool-list time, so changes take effect immediately on deploy.
Rollback plan: Revert the PR. Tool descriptions go back to static strings.
Success Criteria
secseessec_historicalmentioned in tool descriptions without callinglist-workspacesif graph_id == "sec"checks remain in tool classesadapters/sec/manifest.pyandschemas/extensions/roboledger.py, not in tool filesOpen Questions
example_queries_tool.pyfor SEC. Could move totool_supplementsor a dedicatedexample_queriesfield onMCPToolConfig.get-graph-info(handler-level, not a tool) also return manifest-enriched metadata (display name, available subgraphs)?References
local/docs/specs/context-aware-mcp-tools.mdrobosystems/middleware/mcp/tools/robosystems/adapters/sec/manifest.pyrobosystems/schemas/extensions/robosystems/config/shared_repositories.py