Sources
Sources Configuration Guide
This guide explains how to configure sources (MCP servers, APIs, local filesystems) in Tentarc.
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 tentarc-agents-docs MCP:
mcp__tentarc-docs__SearchTentarcAgents({ query: "{service} source setup" })
Available guides: GitHub, Linear, Slack, Gmail, Google Calendar, Google Drive, Google Docs, Google Sheets, Outlook, Microsoft Calendar, Teams, SharePoint, Craft, 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 Craft 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__tentarc-docs__SearchTentarcAgents({ 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 "Craft 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 Craft iOS team"
- OAuth authentication]
Agent: [Writes guide.md mentioning "Craft 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 "Craft iOS" project.
You can use it to:
- Search and view issues in Craft 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:
~/.tentarc/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 header auth
"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"
}
}
}
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:
~/.tentarc/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
Provider: gmail, Type: api
Uses OAuth via source_gmail_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 ~/.tentarc/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_gmail_oauth_triggerfor Gmailsource_credential_promptfor API keys/tokens
-
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