Documentation
¶
Overview ¶
Package mcpserver exposes CodeMode as exactly three official MCP tools.
The adapter resolves a trusted subject through the required InvocationResolver before every operation, ignores untrusted client metadata, and projects failures to stable coarse tool text. StaticSubject supports single-user process-owned identity; multi-user hosts must resolve each authenticated request separately. The adapter does not proxy arbitrary downstream MCP tools.
Example (OfficialTransport) ¶
Example_officialTransport connects official MCP sessions and calls execute.
This in-memory sample has one process-owned identity, matching a single-user stdio host. Multi-user hosts must resolve each request from authenticated, host-owned context instead. authz.AllowAll is deliberate in this sample; production hosts normally supply policy.
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/modelcontextprotocol/go-sdk/mcp"
"github.com/meigma/codemode"
"github.com/meigma/codemode/authz"
"github.com/meigma/codemode/mcpserver"
)
func main() {
// lookupInput is the records.lookup argument contract.
type lookupInput struct {
// Key is the required record identifier.
Key string `json:"key"`
// Limit is the optional result bound.
Limit *int64 `json:"limit,omitempty"`
}
// lookupOutput is the records.lookup handler result.
type lookupOutput struct {
// Key is the looked-up record identifier.
Key string `json:"key"`
// Count is the resolved optional limit, or zero when omitted.
Count int64 `json:"count"`
}
builder := codemode.New(codemode.Options{Authorizer: authz.AllowAll()})
codemode.Register(builder, codemode.Capability[lookupInput, lookupOutput]{
Name: "records.lookup",
Summary: "Look up one record by key.",
Handler: func(_ context.Context, _ authz.Subject, input lookupInput) (lookupOutput, error) {
count := int64(0)
if input.Limit != nil {
count = *input.Limit
}
return lookupOutput{Key: input.Key, Count: count}, nil
},
})
root, err := builder.Build()
if err != nil {
panic(err)
}
mcpServer, err := mcpserver.New(
root,
mcpserver.StaticSubject(authz.Subject{ID: "example-user"}),
mcpserver.Options{},
)
if err != nil {
panic(err)
}
serverTransport, clientTransport := mcp.NewInMemoryTransports()
serverSession, err := mcpServer.Connect(context.Background(), serverTransport, nil)
if err != nil {
panic(err)
}
client := mcp.NewClient(&mcp.Implementation{Name: "example-client", Version: "1"}, nil)
clientSession, err := client.Connect(context.Background(), clientTransport, nil)
if err != nil {
panic(err)
}
result, err := clientSession.CallTool(context.Background(), &mcp.CallToolParams{
Name: "execute",
Arguments: map[string]any{
"source": `
def main():
return records.lookup(key="alpha", limit=2)
`,
},
})
if err != nil {
panic(err)
}
if result.IsError {
panic(fmt.Sprint(result.Content))
}
encoded, err := json.Marshal(result.StructuredContent)
if err != nil {
panic(err)
}
fmt.Println(string(encoded))
if err := clientSession.Close(); err != nil {
panic(err)
}
if err := serverSession.Close(); err != nil {
panic(err)
}
}
Output: {"result":{"count":2,"key":"alpha"}}
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func New ¶
New constructs an official MCP server that exposes exactly search_api, describe_api, and execute.
New rejects a nil or typed-nil Service or InvocationResolver. A nil Implementation retains the library identity Name "codemode" and Version "2". Logger is optional. The returned server has no generic downstream MCP forwarding path. Client request metadata is untrusted and ignored.
Types ¶
type InvocationResolver ¶
type InvocationResolver interface {
// Resolve returns the authenticated subject for the current request.
//
// A resolver failure or empty subject ID stops the request before discovery or
// execution. Resolve must not return credential material.
Resolve(ctx context.Context) (authz.Subject, error)
}
InvocationResolver resolves the trusted invocation subject from host-owned Go context.
Implementations must read only typed trusted context established by middleware or process composition. They must not derive identity from program data, tool arguments, or untrusted request metadata.
func ContextSubject ¶
func ContextSubject() InvocationResolver
ContextSubject returns a resolver for subjects installed with authz.WithSubject.
Authentication middleware remains responsible for validating credentials and installing the subject. Client-controlled tool arguments, program source, and MCP request metadata cannot set or replace the stored subject.
func StaticSubject ¶
func StaticSubject(subject authz.Subject) InvocationResolver
StaticSubject returns a resolver that uses subject for every invocation.
StaticSubject is suitable only when process ownership is the authentication boundary, such as a single-user stdio server. Multi-user hosts must resolve a distinct authenticated subject for each request and must not use StaticSubject.
type Options ¶ added in v0.2.0
type Options struct {
// Implementation is the MCP application identity advertised to clients.
// Nil retains Name "codemode" and Version "2". A non-nil value is borrowed
// and passed to the SDK without copying or validating fields.
Implementation *mcp.Implementation
// Logger receives SDK server diagnostics. Nil selects the SDK default logger.
Logger *slog.Logger
}
Options configures official MCP server construction.
type Service ¶
type Service interface {
// Search returns a bounded relevance-ranked scan of enabled capabilities.
Search(query string) (codemode.SearchResponse, error)
// Describe returns one exact enabled capability description or a not-found error.
Describe(name codemode.CapabilityName) (codemode.Description, error)
// Execute runs one bounded program for a trusted authenticated subject and returns only main's final value.
Execute(ctx context.Context, subject authz.Subject, program codemode.Program) (any, error)
}
Service is the inbound adapter's view of an immutable CodeMode server.
The root *codemode.Server implements this port. The adapter does not re-enforce catalog bounds, hidden-capability filtering, or execution restrictions.