Skip to content

Add MCP server registry and support server references in tasks#307

Open
sroussey wants to merge 3 commits intorebuild-clifrom
claude/add-mcp-task-registry-y9KGE
Open

Add MCP server registry and support server references in tasks#307
sroussey wants to merge 3 commits intorebuild-clifrom
claude/add-mcp-task-registry-y9KGE

Conversation

@sroussey
Copy link
Collaborator

Summary

This PR introduces a centralized MCP server registry system that allows MCP tasks to reference pre-configured servers by ID instead of requiring inline configuration. It includes a new repository pattern for managing MCP server configurations and updates all MCP-related tasks to support both registry-based and inline server configuration.

Key Changes

  • New MCP Server Registry System

    • Added McpServerRepository base class for managing MCP server configurations with event emission (server_added, server_removed, server_updated)
    • Added InMemoryMcpServerRepository for in-memory storage of server configurations
    • Added McpServerRegistry with global service registration and input resolver integration
    • Added McpServerSchema defining McpServerConfig and McpServerRecord types
  • Task Configuration Updates

    • Updated McpToolCallTask, McpPromptGetTask, McpResourceReadTask, and McpListTask to support a server property with format "mcp-server"
    • Made transport no longer required in task configs (can be provided via registry reference)
    • Added getMcpServerConfig() helper method to merge registry-based and inline configurations, with inline values taking precedence
    • Updated schema validation to allow either registry reference or inline transport configuration
  • Task Runner Enhancement

    • Added schema-aware input resolution in TaskRunner to resolve format-annotated config properties (like mcp-server references) before task execution
    • Added output schema resolution to handle format-annotated output properties
  • Input Resolver Integration

    • Registered resolveMcpServerFromRegistry() as the handler for "mcp-server" format, enabling automatic resolution of server IDs to full configurations

Implementation Details

  • Server configurations can be provided either via the registry (using a server ID string) or inline in task config
  • Inline configuration values override registry values when both are present
  • The registry uses a tabular storage interface for flexibility in backend implementation
  • All MCP tasks now validate that a transport configuration is available from either source before execution
  • The system integrates with the existing input resolver framework for seamless schema-based resolution

https://claude.ai/code/session_01X1uCtkgCkeH2GJq1QAzUp1

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an MCP server registry to let MCP-related tasks reference pre-configured servers by ID, and updates task execution to resolve format-annotated config/inputs/outputs via the schema input resolver system.

Changes:

  • Introduces MCP server registry primitives (schema, repository, in-memory implementation, global registry + input resolver).
  • Updates MCP tasks to accept a server reference and merge registry-based config with inline overrides.
  • Enhances TaskRunner to resolve schema-annotated config properties and output properties before/after execution.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
packages/tasks/src/task/mcp/McpToolCallTask.ts Adds server reference support and merges resolved server config for tool calls + schema discovery.
packages/tasks/src/task/mcp/McpPromptGetTask.ts Adds server reference support and merges resolved server config for prompt retrieval + schema discovery.
packages/tasks/src/task/mcp/McpResourceReadTask.ts Adds server reference support and merges resolved server config for resource reads.
packages/tasks/src/task/mcp/McpListTask.ts Adds server reference support and merges resolved server config for listing tools/resources/prompts.
packages/tasks/src/mcp-server/McpServerSchema.ts Defines MCP server config/record JSON schemas and related TS types.
packages/tasks/src/mcp-server/McpServerRepository.ts Implements a tabular-storage-backed repository with event emission for server records.
packages/tasks/src/mcp-server/InMemoryMcpServerRepository.ts Provides an in-memory repository implementation.
packages/tasks/src/mcp-server/McpServerRegistry.ts Registers a global MCP server repository service + input resolver for mcp-server references.
packages/tasks/src/common.ts Re-exports the new MCP server registry APIs from the tasks package.
packages/task-graph/src/task/TaskRunner.ts Resolves schema-annotated config and output properties via resolveSchemaInputs() during task runs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +252 to +269
private getMcpServerConfig(input: McpListTaskInput): McpServerConfig {
const server = (input as Record<string, unknown>).server as
| Record<string, unknown>
| string
| undefined;
const base = typeof server === "object" && server !== null ? server : {};
const merged = { ...base } as Record<string, unknown>;
for (const key of ["transport", "server_url", "command", "args", "env"] as const) {
const val = (input as Record<string, unknown>)[key];
if (val !== undefined) {
merged[key] = val;
}
}
if (!merged.transport) {
throw new Error("MCP server transport is required (provide inline or via server registry)");
}
return merged as unknown as McpServerConfig;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +136 to +145
// Resolve schema-annotated config properties (e.g., mcp-server references)
const configSchemaResult = (this.task.constructor as typeof Task).configSchema();
if (configSchemaResult) {
const resolvedConfig = await resolveSchemaInputs(
this.task.config as Record<string, unknown>,
configSchemaResult,
{ registry: this.registry }
);
Object.assign(this.task.config, resolvedConfig);
}
Comment on lines +229 to +238
// Resolve schema-annotated config properties (e.g., mcp-server references)
const configSchemaResult = (this.task.constructor as typeof Task).configSchema();
if (configSchemaResult) {
const resolvedConfig = await resolveSchemaInputs(
this.task.config as Record<string, unknown>,
configSchemaResult,
{ registry: this.registry }
);
Object.assign(this.task.config, resolvedConfig);
}
Comment on lines +10 to +14
* A lightweight MCP server configuration suitable for task config/input schemas.
*
* When a string `server_id` is provided, the input resolver system resolves it
* to the full server record from the registry.
*/
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +42 to +45
required: ["tool_name"],
if: { properties: { transport: { const: "stdio" } }, required: ["transport"] },
then: { required: ["command"] },
else: { required: ["server_url"] },
else: {},
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +19 to +23
export type McpServerEventListeners = {
server_added: (server: McpServerRecord) => void;
server_removed: (server: McpServerRecord) => void;
server_updated: (server: McpServerRecord) => void;
};
Comment on lines +66 to +67
// Register the MCP server resolver for format: "mcp-server"
registerInputResolver("mcp-server", resolveMcpServerFromRegistry);
Comment on lines +226 to +238
private getMcpServerConfig(): McpServerConfig | undefined {
const server = this.config.server as Record<string, unknown> | string | undefined;
const base = typeof server === "object" && server !== null ? server : {};
const merged = { ...base } as Record<string, unknown>;
// Inline fields override registry values
for (const key of ["transport", "server_url", "command", "args", "env"] as const) {
if (this.config[key] !== undefined) {
merged[key] = this.config[key];
}
}
if (!merged.transport) return undefined;
return merged as unknown as McpServerConfig;
}
Comment on lines +42 to +45
required: ["prompt_name"],
if: { properties: { transport: { const: "stdio" } }, required: ["transport"] },
then: { required: ["command"] },
else: { required: ["server_url"] },
else: {},
Comment on lines +41 to 45
required: ["resource_uri"],
if: { properties: { transport: { const: "stdio" } }, required: ["transport"] },
then: { required: ["command"] },
else: { required: ["server_url"] },
else: {},
allOf: mcpServerConfigSchema.allOf,
Copy link
Contributor

Copilot AI commented Mar 13, 2026

@sroussey I've opened a new pull request, #309, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Mar 13, 2026

@sroussey I've opened a new pull request, #310, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Mar 13, 2026

@sroussey I've opened a new pull request, #311, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Mar 13, 2026

@sroussey I've opened a new pull request, #312, to work on those changes. Once the pull request is ready, I'll request review from you.

claude added 2 commits March 19, 2026 06:45
…hemas

- Create McpServerSchema, McpServerRepository, InMemoryMcpServerRepository,
  and McpServerRegistry following the ModelRegistry pattern
- MCP servers can now be registered once and referenced by string ID
  (format: "mcp-server") in task configs and inputs
- Extend TaskRunner to run resolveSchemaInputs on config and output schemas,
  not just input schemas, making the resolver system uniform
- Add optional 'server' field to all MCP task configs (ToolCall, ResourceRead,
  PromptGet) and McpListTask input, with backward-compatible inline config
- Inline config fields override registry values for per-task customization

https://claude.ai/code/session_01X1uCtkgCkeH2GJq1QAzUp1
…us re-export

The workglow meta-package re-exports both @workglow/util and @workglow/tasks,
which both exported a type named McpServerConfig. Renamed the tasks version
to McpServerTaskConfig to avoid the TS2308 ambiguity error.

https://claude.ai/code/session_01X1uCtkgCkeH2GJq1QAzUp1
@sroussey sroussey force-pushed the claude/add-mcp-task-registry-y9KGE branch from 8e182c2 to 0699590 Compare March 19, 2026 06:47
@sroussey sroussey changed the base branch from main to rebuild-cli March 19, 2026 06:54
@sroussey sroussey requested a review from Copilot March 19, 2026 07:22
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an MCP server registry/repository so MCP-related tasks can reference preconfigured servers by ID (via format: "mcp-server") instead of requiring full inline server configuration, and updates task execution to resolve schema-annotated config/outputs before running.

Changes:

  • Added MCP server schema + repository + global registry integration (including an input resolver for "mcp-server").
  • Updated MCP tasks (tool call, prompt get, resource read, list) to accept a server reference and merge it with inline overrides.
  • Enhanced TaskRunner to resolve schema-annotated config properties and output properties via resolveSchemaInputs().

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
packages/tasks/src/task/mcp/McpToolCallTask.ts Adds server reference support and merges registry + inline MCP config for tool calls.
packages/tasks/src/task/mcp/McpPromptGetTask.ts Adds server reference support and merges registry + inline MCP config for prompt retrieval.
packages/tasks/src/task/mcp/McpResourceReadTask.ts Adds server reference support and merges registry + inline MCP config for resource reads.
packages/tasks/src/task/mcp/McpListTask.ts Adds server reference support and merges registry + inline MCP config for listing tools/resources/prompts.
packages/tasks/src/mcp-server/McpServerSchema.ts Introduces schemas/types for MCP server configs and persisted records.
packages/tasks/src/mcp-server/McpServerRepository.ts Adds a repository abstraction with event emission for MCP server records.
packages/tasks/src/mcp-server/InMemoryMcpServerRepository.ts Provides an in-memory repository implementation.
packages/tasks/src/mcp-server/McpServerRegistry.ts Registers a global MCP server repository + input resolver for "mcp-server".
packages/tasks/src/common.ts Exports MCP server registry/repository/schema APIs from @workglow/tasks.
packages/task-graph/src/task/TaskRunner.ts Resolves schema-annotated config and output properties before/after task execution.
examples/cli/src/storage.ts Switches CLI MCP persistence to use McpServerRepository and shared schemas.
examples/cli/src/lib.ts Renames exported CLI factory to createMcpServerRepository.
examples/cli/src/commands/mcp.ts Updates CLI MCP commands to use the new repository + server_id schema.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +228 to +235
const merged = { ...base } as Record<string, unknown>;
for (const key of ["transport", "server_url", "command", "args", "env"] as const) {
if (this.config[key] !== undefined) {
merged[key] = this.config[key];
}
}
if (!merged.transport) return undefined;
return merged as unknown as McpServerConfig;
Comment on lines +251 to +255
transport: cfg.transport,
server_url: cfg.server_url,
command: cfg.command,
args: cfg.args,
env: cfg.env,
Comment on lines +41 to 45
required: ["resource_uri"],
if: { properties: { transport: { const: "stdio" } }, required: ["transport"] },
then: { required: ["command"] },
else: { required: ["server_url"] },
else: {},
allOf: mcpServerConfigSchema.allOf,
Comment on lines +128 to +135
for (const key of ["transport", "server_url", "command", "args", "env"] as const) {
if (this.config[key] !== undefined) {
merged[key] = this.config[key];
}
}
if (!merged.transport) {
throw new Error("MCP server transport is required (provide inline or via server registry)");
}
Comment on lines +12 to +13
* When a string `server_id` is provided, the input resolver system resolves it
* to the full server record from the registry.
Comment on lines +230 to +236
// Inline fields override registry values
for (const key of ["transport", "server_url", "command", "args", "env"] as const) {
if (this.config[key] !== undefined) {
merged[key] = this.config[key];
}
}
if (!merged.transport) return undefined;
then: { required: ["command"] },
else: { required: ["server_url"] },
else: {},
allOf: mcpServerConfigSchema.allOf,
Comment on lines +253 to +257
transport: cfg.transport,
server_url: cfg.server_url,
command: cfg.command,
args: cfg.args,
env: cfg.env,
},
required: ["transport", "list_type"],
required: ["list_type"],
allOf: mcpServerConfigSchema.allOf,
Comment on lines +139 to +140
const resolvedConfig = await resolveSchemaInputs(
this.task.config as Record<string, unknown>,
@sroussey
Copy link
Collaborator Author

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link
Contributor

Copilot AI commented Mar 19, 2026

@sroussey I've opened a new pull request, #321, to work on those changes. Once the pull request is ready, I'll request review from you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants