-
Notifications
You must be signed in to change notification settings - Fork 1
MCP
Frags supports the Model Context Protocol (MCP). MCP is an open standard that enables LLMs to securely access and consume remote functions and tools. To utilize them, an MCP server must be running, which Frags will connect to and map to executable functions.
Enabling and using MCP servers involves two main steps:
- Configuring the server connections (at the runner/CLI level).
- Enabling specific MCP servers inside sessions (at the plan/session level).
To enable MCP servers in the CLI, create or update a tools.json file in the root directory of your project. Define your servers under the "mcpServers" block.
Frags supports two types of MCP servers:
- Local/Stdio Servers: Executables or scripts run locally on your system.
- Remote Servers: Servers hosted remotely, connected over HTTP/Streamable HTTP or SSE (Server-Sent Events).
Here is a comprehensive tools.json example demonstrating both local and remote servers, including standard configuration fields and advanced authentication parameters:
{
"mcpServers": {
"local-toolbox": {
"command": "toolbox-binary",
"args": [
"--stdio",
"--profile",
"default"
],
"env": {
"DB_PROJECT": "my-local-project",
"DEBUG": "true"
},
"cwd": "/path/to/working/dir",
"disabled": false
},
"remote-service": {
"url": "https://mcp.example.com/mcp",
"transport": "sse",
"headers": {
"x-custom-origin": "frags-client"
},
"disabled": false,
"client_id": "your-oauth-client-id",
"client_secret": "your-oauth-client-secret",
"authorization_url": "https://auth.example.com/oauth/authorize",
"token_url": "https://auth.example.com/oauth/token"
}
}
}| Field Name | Type | Description |
|---|---|---|
command |
string |
The executable/command name to run for local stdio-based servers. |
args |
array |
Command-line arguments passed to the local command. |
env |
object |
Environment variables injected into the local process. |
cwd |
string |
Working directory in which the local process is spawned. |
url |
string |
The endpoint URL for a remote SSE or Streamable HTTP server. |
transport |
string |
The HTTP transport protocol. Can be "sse" or omitted (defaults to Streamable HTTP with an SSE fallback). |
headers |
object |
Custom HTTP headers sent with the requests to the remote server. |
disabled |
boolean |
If set to true, Frags will completely ignore this server. |
token |
string |
A static API key or Personal Access Token (PAT). Injects "Authorization: Bearer <token>" and bypasses the OAuth browser flow. |
client_id |
string |
The Client ID for OAuth2 authentication (defaults to "frags-client"). |
client_secret |
string |
The Client Secret for OAuth2 authentication. |
authorization_url |
string |
Explicit OAuth2 authorization endpoint. Bypasses discovery if set. |
token_url |
string |
Explicit OAuth2 token exchange endpoint. Bypasses discovery if set. |
pre_authorized_oauth |
object |
Pre-configured authentication token result structure (used to pre-populate authentication cache). |
Frags provides native, secure, and flexible ways to authorize requests with remote servers.
For quick integrations or systems that use Personal Access Tokens:
-
The
tokenProperty: Configure"token": "your_api_token"inside your server block. Frags will automatically inject this as anAuthorization: Bearer your_api_tokenheader and skip any OAuth flow. -
Manual Headers: Alternatively, you can directly set custom headers in the
"headers"block. If an"Authorization"header is detected inside the"headers"object, Frags skips all automatic authentication.
For remote MCP servers implementing the Model Context Protocol OAuth 2.1 flow, Frags performs automated, secure 3-legged authorization.
Frags queries the remote server to find the appropriate authorization and token endpoints dynamically via:
- OAuth2 metadata discovery (RFC 8414)
- Resource endpoint probing (RFC 9728)
If your remote server uses non-standard routes, you can bypass discovery by explicitly defining authorization_url and token_url in tools.json.
If no valid token is found:
- Frags initializes an interactive flow and starts a temporary local HTTP server listening on
http://localhost:9999/callback(the default callback URL). - It automatically opens your default system browser to the server's authorization screen.
- Once authorized in the browser, the callback server captures the authorization code, exchanges it for Access and Refresh tokens, and safely terminates.
- Tokens are cached securely inside
./tokens.jsonwith restrictive0600permissions. -
Transparent Background Refresh: For all subsequent runs, Frags checks
./tokens.json. If a token has expired, Frags will transparently refresh it in the background using the stored refresh token prior to communicating with the server.
When running inside containers, virtual machines, CI/CD pipelines, or headless servers where a browser is unavailable:
- Set the environment variable
OAUTH_DISABLED=true(or configure it in your.envor application config file). - When set, Frags switches to headless mode (
NewEmptyOauthProvider(true)), uses a temporaryInMemoryCache, and completely disables browser launches and callback port listening. - If no valid token is found in memory or configured directly, the connection will fail immediately instead of blocking.
Once configured, servers are registered with Frags. However, to prevent context bloat and ensure security, servers must be explicitly enabled per session in your session configuration (YAML file).
Use the tools list in your sessions to allow access to the MCP server:
sessions:
code_review:
prePrompt: "Analyze the open pull requests."
prompt: "Highlight security vulnerabilities or missing tests."
tools:
- name: github-server # Must match the key configured in tools.json
type: mcpYou can limit which specific remote tools an LLM can invoke by setting an allowlist array on the session tool:
sessions:
code_review:
prompt: "Check PR changes."
tools:
- name: github-server
type: mcp
allowlist:
- github_view_pr
- github_list_commentsIf integrating Frags into your own Go applications, you can manage MCP tools and configure custom OAuth flows programmatically.
To establish connections to an MCP server:
import (
"context"
"github.com/fragshq/frags"
)
// Instantiate and connect to standard stdio or remote MCP servers
mcpTool := frags.NewMcpTool(name, serverConfig)
if err := mcpTool.Connect(ctx, logger); err != nil {
return err
}
// Convert tools to executable functions
functions, err := mcpTool.AsFunctions(ctx)
if err != nil {
return err
}
// Register with your AI engine
ai.SetFunctions(functions)You can pass custom OAuth providers and cache implementations when setting up your programmatic tools. This is ideal for managing headless vs interactive environments:
import (
"github.com/fragshq/frags"
"github.com/fragshq/frags/mcpauth"
)
mcpTools := toolsConfig.McpServers.McpTools()
if oauthDisabled {
// Non-interactive headless mode: InMemoryCache, no browser flow
mcpTools.WithOAuthProvider(
mcpauth.NewEmptyOauthProvider(true).WithCache(mcpauth.NewInMemoryCache()),
)
} else {
// Interactive mode: Persistent file cache, local callback flow
oauthCache, err := mcpauth.NewFsOauthCache("./tokens.json")
if err != nil {
log.Fatalf("failed to load token cache: %v", err)
}
mcpTools.WithOAuthProvider(
mcpauth.NewEmptyOauthProvider(false).WithCache(oauthCache),
)
}
// Establish connections and negotiate tools
if err := mcpTools.Connect(ctx, logger); err != nil {
log.Fatalf("failed to connect to MCP servers: %v", err)
}