Sources Configuration Guide
This guide explains how to configure sources (MCP servers, APIs, local filesystems) in Fabric Agent.
This guide explains how to configure sources (MCP servers, APIs, local filesystems) in Fabric Agent.
Source Setup Process
When a user wants to add a new source, follow this conversational setup process to create a tailored, well-documented integration.
0. Search for Specialized Source Guide (REQUIRED FIRST STEP)
Before doing anything else, search for a specialized guide using the fabric-agents-docs MCP:
mcp__fabric-agents-docs__SearchFabricAgents({ query: "{service} source setup" })Available guides: GitHub, Linear, Slack, Gmail, Google Calendar, Google Drive, Google Docs, Google Sheets, Outlook, Microsoft Calendar, Teams, SharePoint, Fabric, Filesystem, Brave Search, Memory
If a guide exists for the service:
- Read the guide content carefully
- Pay special attention to the "Setup Hints" section - it contains critical instructions
- Follow any CRITICAL/MANDATORY instructions before proceeding (e.g., GitHub requires checking for
ghCLI first) - ALWAYS verify current API endpoints via WebSearch - URLs change frequently
Why this matters: Some services have important prerequisites or gotchas that MUST be checked before creating a source. Skipping this step can lead to failed setups or redundant configurations.
1. Understand User Intent
Before creating any configuration, ask questions to understand:
- Primary purpose: What do they want to accomplish with this source?
- Scope: Specific projects, teams, repositories, or data to focus on?
- Common tasks: What operations will they perform most often?
- Access level: Read-only exploration or full access?
Example questions:
"I'd be happy to help set up Linear! A few questions:
- What will you primarily use Linear for? (issue tracking, sprint planning, etc.)
- Are there specific teams or projects you want to focus on?
- Should I set it up for read-only exploration or full access?"
2. Research the Service
Use available tools to learn about the service:
- WebSearch: Find official documentation, API references, best practices
- Look up: Rate limits, quotas, authentication methods
- Identify: Key endpoints or tools relevant to user's stated goals
- Note: Any limitations or gotchas to document
3. Configure Intelligently
Based on research and user intent, create config.json with ALL required fields:
Required fields:
id- REQUIRED: Unique identifier string. Format:{slug}_{random}(e.g.,linear_a1b2c3d4). Generate the random part with any method (e.g., 8 hex chars).name,slug,provider,type- Basic identificationicon- REQUIRED: URL to the service's favicon, logo, or app icon. Search the web to find an appropriate icon that looks like an app icon. The icon is auto-downloaded and cached locally. Use an emoji as fallback.tagline- REQUIRED: Short description for agent context (e.g., "Issue tracking, sprint planning, and project management")- Type-specific config (
mcp,api, orlocal) - Authentication method appropriate for the service
4. Configure Explore Mode Permissions (REQUIRED)
Sources should work in Explore mode by default. Create permissions.json to allow read-only operations.
How it works: Patterns in a source's permissions.json are automatically scoped to that source. Write simple patterns like list - the system converts them to mcp__<sourceSlug>__.*list internally. This prevents cross-source leakage.
For MCP sources:
- After connecting, list the server's available tools
- Identify read-only tools (list, get, search, find, query operations)
- Create simple patterns for those operations
{
"allowedMcpPatterns": [
{ "pattern": "list", "comment": "All list operations" },
{ "pattern": "get", "comment": "All get/read operations" },
{ "pattern": "search", "comment": "All search operations" },
{ "pattern": "find", "comment": "All find operations" }
]
}For API sources:
{
"allowedApiEndpoints": [
{ "method": "GET", "path": ".*", "comment": "All GET requests are read-only" },
{ "method": "POST", "path": "^/search", "comment": "Search endpoint (read-only despite POST)" }
]
}For local sources:
{
"allowedBashPatterns": [
{ "pattern": "^(ls|cat|head|tail|grep|find|tree)\\s", "comment": "Read-only commands" }
]
}Goal: Sources should be fully functional in Explore mode. Allow all read operations by default. Only block actual mutations (create, update, delete).
5. Write Comprehensive guide.md
Create a guide.md tailored to the user's context:
- Summarize the source's purpose in their specific use case
- Document capabilities relevant to their workflow
- Include specific project/team/scope references they mentioned
- Add usage examples tailored to their tasks
- Note rate limits, quotas, or limitations
6. Test and Validate (MANDATORY)
You MUST use the source_test tool after creating any source. This applies to ALL source types - MCP, API, and local filesystem sources. This is not optional.
mcp__session__source_test({ sourceSlug: "{slug}" })The source_test tool:
- Validates config.json against the schema
- Downloads and caches the icon if a URL was provided
- Tests the connection to verify the source is reachable
- Reports missing fields (icon, tagline) that should be added
After validation passes, trigger the appropriate auth flow:
- OAuth sources:
source_oauth_trigger({ sourceSlug: "{slug}" }) - Bearer/API key:
source_credential_prompt({ sourceSlug: "{slug}", mode: "bearer" }) - Google services:
source_google_oauth_trigger({ sourceSlug: "{slug}" }) - Microsoft services:
source_microsoft_oauth_trigger({ sourceSlug: "{slug}" }) - Slack:
source_slack_oauth_trigger({ sourceSlug: "{slug}" })
Do NOT skip validation - it catches config errors before they cause runtime failures.
guide.md Best Practices
The guide.md file is critical—it helps Claude understand how to use the source effectively in future sessions.
Structure
# Source Name
Brief description of what this source provides and the user's specific use case.
## Scope
What data/functionality this provides. Include:
- Specific projects, teams, or repos the user mentioned
- Relevant filters or defaults
- Any limitations on access
## Guidelines
- Best practices for using this source
- Rate limits or quotas to be aware of
- Common patterns the user will need
- Things to avoid or be careful about
## Examples
Concrete examples tailored to the user's workflow:
- "To find issues in the Fabric iOS project: ..."
- "To search for recent commits by the mobile team: ..."Key Principles
- Be specific to user context: Reference the projects, teams, and tasks they mentioned
- Include concrete examples: Use their actual project names and workflows
- Document user preferences: Any preferences they shared for future sessions
- Note scope boundaries: What the source can and cannot do
- Keep it actionable: Focus on what Claude needs to know to help effectively
Example Conversational Flow
User: I want to add Linear
Agent: [FIRST: Searches for Linear guide]
mcp__fabric-agents-docs__SearchFabricAgents({ query: "linear source setup" })
Agent: I found the Linear setup guide! A few questions:
1. What will you primarily use Linear for? (issue tracking, sprint planning, reporting?)
2. Are there specific teams or projects you want to focus on?
3. Should I set it up for read-only exploration or full access?
User: Issue tracking for my iOS team, project called "Fabric iOS"
Agent: [Uses WebSearch to verify current Linear MCP URL]
Agent: [Creates config.json with:
- icon: (searches web for app icon or uses favicon)
- tagline: "Issue tracking for the Fabric iOS team"
- OAuth authentication]
Agent: [Writes guide.md mentioning "Fabric iOS" project and iOS team context]
Agent: [Sets up permissions.json for read-only listing in Explore mode]
Agent: [MANDATORY: Runs source_test to validate]
mcp__session__source_test({ sourceSlug: "linear" })
Agent: [Triggers source_oauth_trigger for authentication]
mcp__session__source_oauth_trigger({ sourceSlug: "linear" })
Agent: Linear is now set up! I've configured it to focus on the "Fabric iOS" project.
You can use it to:
- Search and view issues in Fabric iOS
- Track sprint progress for the iOS team
- Create and update issues
Would you like me to show you what issues are currently open?Overview
Sources are stored as folders under:
~/.fabric-agent/workspaces/{workspaceId}/sources/{sourceSlug}/
Each source folder contains:
config.json- Source configuration (required)guide.md- Usage documentation for Claude (optional)permissions.json- Custom permission rules for Explore mode (optional)icon.svg,icon.png,icon.jpg, oricon.jpeg- Source icon (optional)
config.json Schema
{
"id": "linear_a1b2c3d4", // Unique identifier: {slug}_{random}
"name": "Human-readable name",
"slug": "url-safe-identifier",
"enabled": true,
"provider": "provider-name",
"type": "mcp" | "api" | "local",
// REQUIRED: Icon and tagline for UI and agent context
"icon": "https://example.com/favicon.ico", // URL (auto-downloaded) or emoji
"tagline": "Brief description for agent context",
// For MCP sources:
"mcp": {
"url": "https://mcp.example.com",
"authType": "oauth" | "bearer" | "none"
},
// For API sources:
"api": {
"baseUrl": "https://api.example.com/", // MUST have trailing slash
"authType": "bearer" | "header" | "query" | "basic" | "none",
"headerName": "X-API-Key", // For single header auth
"headerNames": ["X-API-KEY", "X-APP-KEY"], // For multi-header auth (2+ headers)
"queryParam": "api_key", // For query auth
"authScheme": "Bearer" // For bearer auth (default: "Bearer")
},
// For local sources:
"local": {
"path": "/path/to/folder"
},
// Status (updated by source_test):
"isAuthenticated": true,
"connectionStatus": "connected" | "needs_auth" | "failed" | "untested",
"lastTestedAt": 1704067200000,
// Icon: emoji or URL (auto-downloaded to local icon.* file)
// Local icon files are auto-discovered, no config needed
"icon": "🔧", // Emoji icon (optional)
// Timestamps:
"createdAt": 1704067200000,
"updatedAt": 1704067200000
}Source Types
MCP Sources
Model Context Protocol servers provide tools via HTTP/SSE.
OAuth authentication (recommended):
{
"id": "linear_a1b2c3d4",
"type": "mcp",
"provider": "linear",
"mcp": {
"url": "https://mcp.linear.app",
"authType": "oauth"
}
}After creating, use source_oauth_trigger to authenticate.
Bearer token authentication:
{
"type": "mcp",
"provider": "custom-mcp",
"mcp": {
"url": "https://my-mcp-server.com",
"authType": "bearer"
}
}After creating, use source_credential_prompt with mode "bearer".
Public (no auth):
{
"type": "mcp",
"provider": "public-mcp",
"mcp": {
"url": "https://public-mcp.example.com",
"authType": "none"
}
}Stdio transport (local command):
For MCP servers that run locally via command line (npx, node, python), use the stdio transport.
Users often provide configs in Claude Desktop / Claude Code format:
{
"mcpServers": {
"airbnb": {
"command": "npx",
"args": ["-y", "@openbnb/mcp-server-airbnb"]
}
}
}Convert to native format:
{
"type": "mcp",
"name": "Airbnb",
"provider": "airbnb",
"mcp": {
"transport": "stdio",
"command": "npx",
"args": ["-y", "@openbnb/mcp-server-airbnb"],
"authType": "none"
}
}With environment variables:
{
"type": "mcp",
"name": "Brave Search",
"provider": "brave",
"mcp": {
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": {
"BRAVE_API_KEY": "your-api-key"
},
"authType": "none"
}
}API Sources
REST APIs become flexible tools that Claude can call.
IMPORTANT: Authenticated API sources require a testEndpoint to validate credentials during source_test. Without it, we cannot verify your credentials work.
Header authentication (X-API-Key style):
{
"type": "api",
"provider": "exa",
"api": {
"baseUrl": "https://api.exa.ai/",
"authType": "header",
"headerName": "x-api-key",
"testEndpoint": {
"method": "POST",
"path": "search",
"body": { "query": "test", "numResults": 1 }
}
}
}Bearer token (Authorization header):
{
"type": "api",
"provider": "openai",
"api": {
"baseUrl": "https://api.openai.com/v1/",
"authType": "bearer",
"testEndpoint": {
"method": "GET",
"path": "models"
}
}
}Query parameter:
{
"type": "api",
"provider": "weather",
"api": {
"baseUrl": "https://api.weather.com/",
"authType": "query",
"queryParam": "apikey",
"testEndpoint": {
"method": "GET",
"path": "v1/current"
}
}
}Basic authentication:
{
"type": "api",
"provider": "jira",
"api": {
"baseUrl": "https://your-domain.atlassian.net/rest/api/3/",
"authType": "basic",
"testEndpoint": {
"method": "GET",
"path": "myself"
}
}
}Multi-header authentication:
Some APIs require multiple authentication headers simultaneously. For example, Datadog requires both DD-API-KEY and DD-APPLICATION-KEY. Use the headerNames array to specify all required headers:
{
"type": "api",
"provider": "datadog",
"api": {
"baseUrl": "https://api.datadoghq.com/api/",
"authType": "header",
"headerNames": ["DD-API-KEY", "DD-APPLICATION-KEY"],
"testEndpoint": {
"method": "GET",
"path": "v1/validate"
}
}
}When headerNames is specified:
- Each header name gets its own input field during authentication
- All header values are stored together as a JSON object
- Each header is added to every API request
To prompt for multi-header credentials:
source_credential_prompt({
sourceSlug: "datadog",
mode: "multi-header",
headerNames: ["DD-API-KEY", "DD-APPLICATION-KEY"],
description: "Enter your Datadog API credentials"
})Common multi-header use cases:
- Datadog:
DD-API-KEY+DD-APPLICATION-KEY - APIs with identity + signing keys: Separate API key and secret
- Services with app + user credentials: Application key plus user token
Basic auth with optional password:
Some APIs use HTTP Basic Auth but only require the username field (API key), leaving the password empty. For these APIs, use passwordRequired: false when prompting for credentials:
source_credential_prompt({
sourceSlug: "ashby",
mode: "basic",
passwordRequired: false, // Password field becomes optional
labels: { username: "API Key" },
description: "Enter your Ashby API key"
})When passwordRequired: false:
- The password field shows "(optional)" label and "Optional - leave blank" placeholder
- The Save button enables with just a username
- Empty string is submitted for password (per HTTP Basic Auth spec:
base64(username:))
Note: passwordRequired only applies to mode: "basic". It defaults to true for backward compatibility with services like Jira or Amplitude that require both username and password.
testEndpoint Configuration
The testEndpoint specifies which endpoint to call when validating credentials:
{
"testEndpoint": {
"method": "GET", // "GET" or "POST"
"path": "v1/me", // Path relative to baseUrl (NO leading slash)
"body": { ... } // Optional: request body for POST
}
}IMPORTANT URL formatting:
baseUrlMUST have a trailing slash:https://api.example.com/v1/testEndpoint.pathmust NOT have a leading slash:users/me
Choose an endpoint that:
- Requires authentication (to verify credentials work)
- Is lightweight (doesn't fetch much data)
- Returns quickly (health/status endpoints are ideal)
Common patterns:
me,user,profile- User info endpointsv1/status,health- Status endpoints that require authmodels,projects- List endpoints with minimal data
Public APIs (authType: 'none') don't require testEndpoint - we test by hitting the base URL.
Local Sources
Filesystem access for local folders.
{
"type": "local",
"provider": "obsidian",
"local": {
"path": "/Users/me/Documents/ObsidianVault"
}
}After creating, run source_test to validate the path exists and is accessible.
guide.md Format
The guide.md file helps Claude understand how to use the source effectively.
# Source Name
Brief description of what this source provides.
## Scope
What data/functionality this source provides access to.
## Guidelines
- Best practices for using this source
- Rate limits or quotas to be aware of
- Common patterns and examples
## API Reference
For API sources, document the available endpoints:
### POST /search
Search for content.
**Parameters:**
- `query` (string, required): Search query
- `limit` (number, optional): Max results (default: 10)
**Example:**
\`\`\`json
{
"query": "machine learning",
"limit": 5
}
\`\`\`permissions.json Format
Custom rules to extend Explore mode permissions for this source.
{
"allowedMcpPatterns": [
{
"pattern": "^mcp__linear__list",
"comment": "Allow listing resources in Explore mode"
}
],
"allowedApiEndpoints": [
{
"method": "GET",
"path": "^/search",
"comment": "Allow search endpoint in Explore mode"
},
{
"method": "POST",
"path": "^/v1/query$",
"comment": "POST allowed for query-only endpoints"
}
],
"allowedBashPatterns": [
{
"pattern": "^ls\\s",
"comment": "Allow ls commands"
}
]
}Icon Handling
The config.icon field controls the source icon. Resolution follows this priority:
config.icon value | Behavior |
|---|---|
Emoji (e.g., "🔧") | Rendered as emoji text |
Local path "./icon.svg" | Loads from sources/{slug}/icon.svg |
URL "https://..." | Auto-downloaded to local icon.* file by source_test |
| Undefined/null | Auto-discovers sources/{slug}/icon.{svg,png}, falls back to favicon |
Examples:
// Emoji icon
{ "icon": "📝" }
// Explicit local path (rarely needed - auto-discovery handles this)
{ "icon": "./icon.svg" }
// URL (downloaded automatically by source_test)
{ "icon": "https://linear.app/static/favicon.svg" }
// No icon field - auto-discovers icon.svg/icon.png or resolves favicon
{}Best practice: Set icon to a URL when creating a source. Run source_test to download and cache it locally. The app then uses the local file for fast, offline-capable display.
Provider Domain Cache
For favicon resolution, a cache maps provider names to their canonical domains at:
~/.fabric-agent/provider-domains.json
Format:
{
"version": 1,
"domains": {
"linear": "linear.app",
"notion": "notion.so",
"brave": "brave.com"
},
"updatedAt": 1704067200000
}When to update: If a source's favicon appears incorrect (generic globe, wrong icon), add the provider→domain mapping to this file. The app loads this cache on startup.
Example: If "acme-mcp" source shows wrong icon, add:
"acme": "acme.com"Common Providers
Gmail (and other Google services)
Provider: google, Type: api
Requires user-provided OAuth credentials in the source config:
googleOAuthClientId: Your Google OAuth Client IDgoogleOAuthClientSecret: Your Google OAuth Client Secret
Create credentials at Google Cloud Console (Desktop app type).
Uses OAuth via source_google_oauth_trigger.
Linear
Provider: linear, Type: mcp
URL: https://mcp.linear.app, OAuth auth.
GitHub
Provider: github, Type: mcp
URL: https://api.githubcopilot.com/mcp/, bearer auth (PAT required - OAuth will fail).
Exa (Search)
Provider: exa, Type: api
Base URL: https://api.exa.ai, header auth with x-api-key.
Brave Search
Provider: brave, Type: mcp
Transport: stdio, Command: npx -y @modelcontextprotocol/server-brave-search, requires BRAVE_API_KEY env.
Memory
Provider: memory, Type: mcp
Transport: stdio, Command: npx -y @modelcontextprotocol/server-memory, no auth.
Workflow
Creating a Source
Always follow the conversational setup process (see above). The key steps:
- Ask before creating: Understand user intent, scope, and common tasks
- Research before configuring: Use WebSearch to find docs, best practices, limitations
- Tailor guide.md to context: Include specific projects/teams the user mentioned
- Test before declaring done: Validate config, trigger auth, verify connection
Technical steps:
-
Create the source folder:
mkdir -p ~/.fabric-agent/workspaces/{ws}/sources/my-source -
Write
config.jsonwith appropriate settings (see schemas above) -
Write
guide.mdtailored to user's context and use case -
Create
permissions.jsonfor Explore mode - List the source's tools, identify read-only operations (list, get, search), and add simple patterns. Patterns are auto-scoped to this source. -
Run
source_testto validate configuration and test connection -
If auth is required, trigger the appropriate flow:
source_oauth_triggerfor MCP OAuthsource_google_oauth_triggerfor Google services (Gmail, Calendar, Drive, Docs, Sheets)source_microsoft_oauth_triggerfor Microsoft servicessource_slack_oauth_triggerfor Slacksource_credential_promptfor API keys/tokens- For basic auth with optional password:
source_credential_prompt({ mode: "basic", passwordRequired: false })
-
Confirm with user that the source is working as expected
Testing a Source
Use source_test with the source slug:
- Validates config.json schema
- Tests connectivity
- Downloads icon if needed
- Updates connectionStatus
Troubleshooting
"needs_auth" status:
- Source requires authentication
- Use appropriate auth trigger tool
"failed" status:
- Check
connectionErrorin config.json - Verify URL is correct
- Check network connectivity
Icon not showing:
- Ensure iconUrl is valid
- Run
source_testto re-download - Check file exists in source folder