Skip to content

Schema-Based Tool Registration and Handling #92

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

KeithBird
Copy link

Overview

Introduces the @Schemable macro for type-safe, schema-driven tool handling in MCP servers.

Key Features

  • Type Safety: Built-in argument validation with error reporting
  • Server Extension: Adds a withTools method that automatically configures MCP's listTools and callTool methods.
  • SchemaTool: A generic struct for defining tools with a schema-based input and async handler.
  • ToolBox: A variadic container for grouping multiple SchemaTool instances, allowing batch registration with the server.

Example Usage

@Schemable
struct EchoInput {
    @SchemaOptions(description: "The message to echo")
    let message: String
}

let echoTool = SchemaTool(
    name: "echo",
    description: "Echoes back the input string.",
    inputType: EchoInput.self
) { input in
    .init(content: [.text(input.message)], isError: false)
}

server.withTools(ToolBox(tools: (echoTool)))

Motivation

  • Safety: Ensures all tool invocations are validated against a schema, reducing runtime errors.
  • Efficient: Makes it easy to add new tools with minimal boilerplate.

Implementation

  • Includes schema parsing and MCP tool conversion utilities
  • Uses Swift’s variadic generics for ergonomic tool registration.
  • Seamless integration with existing MCP server and tool protocols.

How Has This Been Tested?

Unit test in SchemaMCP/Tests/Test.swift. Already tested in a real application.

Breaking Changes

Important:

This PR introduces a dependency on the swift-json-schema library, which has higher minimum OS version requirements than the current library.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Design Inspiration

This interface's design draws inspiration from best practices found in two major MCP libraries:

Additional context

I'm opening this PR directly for discussion purposes. Since the implementation is relatively small (primarily in SchemaTool.swift), I believe it's more efficient to discuss the actual code.
Note that this branch is intended for discussion only, as the swift-json-schema dependency requires a higher minimum version than our current library supports.

@KeithBird KeithBird marked this pull request as draft April 27, 2025 10:32
@mattt
Copy link
Contributor

mattt commented Apr 27, 2025

Hi @KeithBird. Thanks for opening this PR. There's a thread about designing a high-level API in #27.

I think one of the requirements for a high-level API is the ability to dynamically add and remove tools, which I think will require an entirely separate layer on top of what we have now with Server.

Regarding swift-json-schema, I also looked at this package, but found it to be too heavy of a dependency for this particular use case. For my own projects, I'm using this one instead.

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.

2 participants