Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 68 additions & 16 deletions docs/docs/features/mcp-server.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -147,32 +147,84 @@ The [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP)

### `search_code`

Fetches code that matches the provided regex pattern in `query`.
Searches for code that matches the provided search query as a substring by default, or as a regular expression if `useRegex` is true.

Parameters:
| Name | Required | Description |
|:----------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------|
| `query` | yes | Regex pattern to search for. Escape special characters and spaces with a single backslash (e.g., 'console\.log', 'console\ log'). |
| `filterByRepoIds` | no | Restrict search to specific repository IDs (from 'list_repos'). Leave empty to search all. |
| `filterByLanguages` | no | Restrict search to specific languages (GitHub linguist format, e.g., Python, JavaScript). |
| `caseSensitive` | no | Case sensitive search (default: false). |
| `includeCodeSnippets` | no | Include code snippets in results (default: false). |
| `maxTokens` | no | Max tokens to return (default: env.DEFAULT_MINIMUM_TOKENS). |
| Name | Required | Description |
|:----------------------|:---------|:---------------------------------------------------------------------------------------------------------------------|
| `query` | yes | The search pattern to match against code contents. Do not escape quotes in your query. |
| `useRegex` | no | Whether to use regular expression matching. When false, substring matching is used (default: false). |
| `filterByRepos` | no | Scope the search to specific repositories. |
| `filterByLanguages` | no | Scope the search to specific languages. |
| `filterByFilepaths` | no | Scope the search to specific filepaths. |
| `caseSensitive` | no | Whether the search should be case sensitive (default: false). |
| `includeCodeSnippets` | no | Whether to include code snippets in the response (default: false). |
| `ref` | no | Commit SHA, branch or tag name to search on. If not provided, defaults to the default branch. |
| `maxTokens` | no | The maximum number of tokens to return (default: 10000). |


### `list_repos`

Lists all repositories indexed by Sourcebot.
Lists repositories indexed by Sourcebot with optional filtering and pagination.

### `get_file_source`
Parameters:
| Name | Required | Description |
|:------------|:---------|:--------------------------------------------------------------------------------|
| `query` | no | Filter repositories by name (case-insensitive). |
| `page` | no | Page number for pagination (min 1, default: 1). |
| `perPage` | no | Results per page for pagination (min 1, max 100, default: 30). |
| `sort` | no | Sort repositories by 'name' or 'pushed' (most recent commit). Default: 'name'. |
| `direction` | no | Sort direction: 'asc' or 'desc' (default: 'asc'). |


### `read_file`

Reads the source code for a given file.

Parameters:
| Name | Required | Description |
|:-------|:---------|:-------------------------------------------------------------------------------------------------------|
| `repo` | yes | The repository name. |
| `path` | yes | The path to the file. |
| `ref` | no | Commit SHA, branch or tag name to fetch the source code for. If not provided, uses the default branch. |


### `list_commits`

Get a list of commits for a given repository.

Parameters:
| Name | Required | Description |
|:----------|:---------|:-----------------------------------------------------------------------------------------------------------------------|
| `repo` | yes | The name of the repository to list commits for. |
| `query` | no | Search query to filter commits by message content (case-insensitive). |
| `since` | no | Show commits more recent than this date. Supports ISO 8601 (e.g., '2024-01-01') or relative formats (e.g., '30 days ago'). |
| `until` | no | Show commits older than this date. Supports ISO 8601 (e.g., '2024-12-31') or relative formats (e.g., 'yesterday'). |
| `author` | no | Filter commits by author name or email (case-insensitive). |
| `ref` | no | Commit SHA, branch or tag name to list commits of. If not provided, uses the default branch. |
| `page` | no | Page number for pagination (min 1, default: 1). |
| `perPage` | no | Results per page for pagination (min 1, max 100, default: 50). |


### `list_language_models`

Lists the available language models configured on the Sourcebot instance. Use this to discover which models can be specified when calling `ask_codebase`.

Parameters:

This tool takes no parameters.


### `ask_codebase`

Fetches the source code for a given file.
Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.

Parameters:
| Name | Required | Description |
|:-------------|:---------|:-----------------------------------------------------------------|
| `fileName` | yes | The file to fetch the source code for. |
| `repoId` | yes | The Sourcebot repository ID. |
| Name | Required | Description |
|:----------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------|
| `query` | yes | The query to ask about the codebase. |
| `repos` | no | The repositories that are accessible to the agent during the chat. If not provided, all repositories are accessible. |
| `languageModel` | no | The language model to use for answering the question. Object with `provider` and `model`. If not provided, defaults to the first model in the config. Use `list_language_models` to see available options. |
Comment on lines +220 to +227
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Capitalize “Markdown” (proper noun).

Minor wording polish for the ask_codebase description.

✏️ Proposed fix
-Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.
+Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in Markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.
Parameters:
| Name | Required | Description |
|:-------------|:---------|:-----------------------------------------------------------------|
| `fileName` | yes | The file to fetch the source code for. |
| `repoId` | yes | The Sourcebot repository ID. |
| Name | Required | Description |
|:----------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------|
| `query` | yes | The query to ask about the codebase. |
| `repos` | no | The repositories that are accessible to the agent during the chat. If not provided, all repositories are accessible. |
| `languageModel` | no | The language model to use for answering the question. Object with `provider` and `model`. If not provided, defaults to the first model in the config. Use `list_language_models` to see available options. |
Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in Markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.
Parameters:
| Name | Required | Description |
|:----------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------|
| `query` | yes | The query to ask about the codebase. |
| `repos` | no | The repositories that are accessible to the agent during the chat. If not provided, all repositories are accessible. |
| `languageModel` | no | The language model to use for answering the question. Object with `provider` and `model`. If not provided, defaults to the first model in the config. Use `list_language_models` to see available options. |
🧰 Tools
🪛 LanguageTool

[uncategorized] ~220-~220: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ... question. Returns a detailed answer in markdown format with code references, plus a lin...

(MARKDOWN_NNP)

🤖 Prompt for AI Agents
In `@docs/docs/features/mcp-server.mdx` around lines 220 - 227, Update the
ask_codebase tool description to capitalize the proper noun "Markdown" and apply
the minor wording polish: change the phrase "Returns a detailed answer in
markdown format with code references, plus a link to view the full research
session in the Sourcebot web UI." to use "Markdown" and improve clarity (e.g.,
"Returns a detailed answer in Markdown format with code references and a link to
view the full research session in the Sourcebot web UI."). Ensure the change is
made in the string for the ask_codebase description and the related
parameter/table text that currently contains "markdown" so the tool name
"ask_codebase" and the table entry for the return description reflect the
corrected capitalization and wording.



## Environment Variables
Expand Down
26 changes: 26 additions & 0 deletions packages/mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,32 @@ Get a list of commits for a given repository.

</details>

### list_language_models

Lists the available language models configured on the Sourcebot instance. Use this to discover which models can be specified when calling `ask_codebase`.

<details>
<summary>Parameters</summary>

This tool takes no parameters.

</details>

### ask_codebase

Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.

<details>
<summary>Parameters</summary>

| Name | Required | Description |
|:----------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------|
| `query` | yes | The query to ask about the codebase. |
| `repos` | no | The repositories that are accessible to the agent during the chat. If not provided, all repositories are accessible. |
| `languageModel` | no | The language model to use for answering the question. Object with `provider` and `model`. If not provided, defaults to the first model in the config. Use `list_language_models` to see available options. |

Comment on lines +248 to +260
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix minor doc/formatting nits (Markdown + table alignment).
These are minor, but will clear the lint hints (MARKDOWN_NNP, MD060).

✏️ Suggested doc fix
-Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.
+Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in Markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.
@@
-| Name            | Required | Description                                                                                                                                    |
-|:----------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------|
-| `query`         | yes      | The query to ask about the codebase.                                                                                                           |
-| `repos`         | no       | The repositories that are accessible to the agent during the chat. If not provided, all repositories are accessible.                           |
-| `languageModel` | no       | The language model to use for answering the question. Object with `provider` and `model`. If not provided, defaults to the first model in the config. Use `list_language_models` to see available options. |
+| Name            | Required | Description                                                                                                                                                                                     |
+| :-------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `query`         | yes      | The query to ask about the codebase.                                                                                                                                                            |
+| `repos`         | no       | The repositories that are accessible to the agent during the chat. If not provided, all repositories are accessible.                                                                           |
+| `languageModel` | no       | The language model to use for answering the question. Object with `provider` and `model`. If not provided, defaults to the first model in the config. Use `list_language_models` to see options. |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### ask_codebase
Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.
<details>
<summary>Parameters</summary>
| Name | Required | Description |
|:----------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------|
| `query` | yes | The query to ask about the codebase. |
| `repos` | no | The repositories that are accessible to the agent during the chat. If not provided, all repositories are accessible. |
| `languageModel` | no | The language model to use for answering the question. Object with `provider` and `model`. If not provided, defaults to the first model in the config. Use `list_language_models` to see available options. |
### ask_codebase
Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question. Returns a detailed answer in Markdown format with code references, plus a link to view the full research session in the Sourcebot web UI.
<details>
<summary>Parameters</summary>
| Name | Required | Description |
| :-------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query` | yes | The query to ask about the codebase. |
| `repos` | no | The repositories that are accessible to the agent during the chat. If not provided, all repositories are accessible. |
| `languageModel` | no | The language model to use for answering the question. Object with `provider` and `model`. If not provided, defaults to the first model in the config. Use `list_language_models` to see options. |
🧰 Tools
🪛 LanguageTool

[uncategorized] ~250-~250: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ... question. Returns a detailed answer in markdown format with code references, plus a lin...

(MARKDOWN_NNP)

🪛 markdownlint-cli2 (0.20.0)

[warning] 259-259: Table column style
Table pipe does not align with header for style "aligned"

(MD060, table-column-style)

🤖 Prompt for AI Agents
In `@packages/mcp/README.md` around lines 248 - 260, The ask_codebase section's
Markdown table has alignment/formatting issues causing MARKDOWN_NNP/MD060 lint
warnings; fix by normalizing the table header and separator row (ensure the
header row uses pipes and the separator row uses matching colons/dashes like
"|:---|:---:|---:|" for intended alignment), make sure each cell is separated by
pipes with consistent whitespace, remove any stray blank lines or mismatched
backticks around column names (e.g., `query`, `repos`, `languageModel`) and
ensure the surrounding details/summary blocks are properly nested so the table
renders as a single contiguous block under the "Parameters" summary in the
ask_codebase section.

</details>


## Supported Code Hosts
Sourcebot supports the following code hosts:
Expand Down
45 changes: 42 additions & 3 deletions packages/mcp/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { env } from './env.js';
import { listReposResponseSchema, searchResponseSchema, fileSourceResponseSchema, listCommitsResponseSchema } from './schemas.js';
import { FileSourceRequest, ListReposQueryParams, SearchRequest, ListCommitsQueryParamsSchema } from './types.js';
import { listReposResponseSchema, searchResponseSchema, fileSourceResponseSchema, listCommitsResponseSchema, askCodebaseResponseSchema, listLanguageModelsResponseSchema } from './schemas.js';
import { AskCodebaseRequest, AskCodebaseResponse, FileSourceRequest, ListReposQueryParams, SearchRequest, ListCommitsQueryParamsSchema, ListLanguageModelsResponse } from './types.js';
import { isServiceError, ServiceErrorException } from './utils.js';
import { z } from 'zod';

Expand Down Expand Up @@ -106,4 +106,43 @@ export const listCommits = async (queryParams: ListCommitsQueryParamsSchema) =>
const commits = await parseResponse(response, listCommitsResponseSchema);
const totalCount = parseInt(response.headers.get('X-Total-Count') ?? '0', 10);
return { commits, totalCount };
}
}

/**
* Asks a natural language question about the codebase using the Sourcebot AI agent.
* This is a blocking call that runs the full agent loop and returns when complete.
*
* @param request - The question and optional repo filters
* @returns The agent's answer, chat URL, sources, and metadata
*/
export const askCodebase = async (request: AskCodebaseRequest): Promise<AskCodebaseResponse> => {
const response = await fetch(`${env.SOURCEBOT_HOST}/api/chat/blocking`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Sourcebot-Client-Source': 'mcp',
...(env.SOURCEBOT_API_KEY ? { 'X-Sourcebot-Api-Key': env.SOURCEBOT_API_KEY } : {})
},
body: JSON.stringify(request),
});

return parseResponse(response, askCodebaseResponseSchema);
}

/**
* Lists the available language models configured on the Sourcebot instance.
*
* @returns Array of language model info objects
*/
export const listLanguageModels = async (): Promise<ListLanguageModelsResponse> => {
const response = await fetch(`${env.SOURCEBOT_HOST}/api/models`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Sourcebot-Client-Source': 'mcp',
...(env.SOURCEBOT_API_KEY ? { 'X-Sourcebot-Api-Key': env.SOURCEBOT_API_KEY } : {})
},
});

return parseResponse(response, listLanguageModelsResponseSchema);
}
56 changes: 53 additions & 3 deletions packages/mcp/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import _dedent from "dedent";
import escapeStringRegexp from 'escape-string-regexp';
import { z } from 'zod';
import { getFileSource, listCommits, listRepos, search } from './client.js';
import { askCodebase, getFileSource, listCommits, listLanguageModels, listRepos, search } from './client.js';
import { env, numberSchema } from './env.js';
import { fileSourceRequestSchema, listCommitsQueryParamsSchema, listReposQueryParamsSchema } from './schemas.js';
import { FileSourceRequest, ListCommitsQueryParamsSchema, ListReposQueryParams, TextContent } from './types.js';
import { askCodebaseRequestSchema, fileSourceRequestSchema, listCommitsQueryParamsSchema, listReposQueryParamsSchema } from './schemas.js';
import { AskCodebaseRequest, FileSourceRequest, ListCommitsQueryParamsSchema, ListReposQueryParams, TextContent } from './types.js';

const dedent = _dedent.withOptions({ alignValues: true });

Expand Down Expand Up @@ -238,7 +238,57 @@ server.tool(
}
);

server.tool(
"list_language_models",
dedent`Lists the available language models configured on the Sourcebot instance. Use this to discover which models can be specified when calling ask_codebase.`,
{},
async () => {
const models = await listLanguageModels();

return {
content: [{
type: "text",
text: JSON.stringify(models),
}],
};
}
);

server.tool(
"ask_codebase",
dedent`
Ask a natural language question about the codebase. This tool uses an AI agent to autonomously search code, read files, and find symbol references/definitions to answer your question.

The agent will:
- Analyze your question and determine what context it needs
- Search the codebase using multiple strategies (code search, symbol lookup, file reading)
- Synthesize findings into a comprehensive answer with code references

Returns a detailed answer in markdown format with code references, plus a link to view the full research session (including all tool calls and reasoning) in the Sourcebot web UI.

This is a blocking operation that may take 30-60+ seconds for complex questions as the agent researches the codebase.
`,
askCodebaseRequestSchema.shape,
async (request: AskCodebaseRequest) => {
const response = await askCodebase(request);

// Format the response with the answer and a link to the chat
const formattedResponse = dedent`
${response.answer}

---
**View full research session:** ${response.chatUrl}
**Model used:** ${response.languageModel.model}
`;

return {
content: [{
type: "text",
text: formattedResponse,
}],
};
}
);

const runServer = async () => {
const transport = new StdioServerTransport();
Expand Down
42 changes: 42 additions & 0 deletions packages/mcp/src/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,45 @@ export const listCommitsResponseSchema = z.array(z.object({
author_name: z.string(),
author_email: z.string(),
}));

export const languageModelInfoSchema = z.object({
provider: z.string().describe("The model provider (e.g., 'anthropic', 'openai')"),
model: z.string().describe("The model ID"),
displayName: z.string().optional().describe("Optional display name for the model"),
});

export const listLanguageModelsResponseSchema = z.array(languageModelInfoSchema);

export const askCodebaseRequestSchema = z.object({
query: z
.string()
.describe("The query to ask about the codebase."),
repos: z
.array(z.string())
.optional()
.describe("The repositories that are accessible to the agent during the chat. If not provided, all repositories are accessible."),
languageModel: languageModelInfoSchema
.omit({ displayName: true })
.optional()
.describe("The language model to use for answering the question. If not provided, defaults to the first model in the config. Use list_language_models to see available options."),
});

export const sourceSchema = z.object({
type: z.literal('file'),
repo: z.string(),
path: z.string(),
name: z.string(),
language: z.string(),
revision: z.string(),
});

export const askCodebaseResponseSchema = z.object({
answer: z.string().describe("The agent's final answer in markdown format"),
chatId: z.string().describe("ID of the persisted chat session"),
chatUrl: z.string().describe("URL to view the chat in the web UI"),
languageModel: z.object({
provider: z.string().describe("The model provider (e.g., 'anthropic', 'openai')"),
model: z.string().describe("The model ID"),
displayName: z.string().optional().describe("Optional display name for the model"),
}).describe("The language model used to generate the response"),
});
10 changes: 10 additions & 0 deletions packages/mcp/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import {
serviceErrorSchema,
listCommitsQueryParamsSchema,
listCommitsResponseSchema,
askCodebaseRequestSchema,
askCodebaseResponseSchema,
languageModelInfoSchema,
listLanguageModelsResponseSchema,
} from "./schemas.js";
import { z } from "zod";

Expand All @@ -34,3 +38,9 @@ export type ServiceError = z.infer<typeof serviceErrorSchema>;

export type ListCommitsQueryParamsSchema = z.infer<typeof listCommitsQueryParamsSchema>;
export type ListCommitsResponse = z.infer<typeof listCommitsResponseSchema>;

export type AskCodebaseRequest = z.infer<typeof askCodebaseRequestSchema>;
export type AskCodebaseResponse = z.infer<typeof askCodebaseResponseSchema>;

export type LanguageModelInfo = z.infer<typeof languageModelInfoSchema>;
export type ListLanguageModelsResponse = z.infer<typeof listLanguageModelsResponseSchema>;
1 change: 1 addition & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
"codemirror-lang-spreadsheet": "^1.3.0",
"codemirror-lang-zig": "^0.1.0",
"date-fns": "^4.1.0",
"dedent": "^1.7.1",
"embla-carousel-auto-scroll": "^8.3.0",
"embla-carousel-react": "^8.3.0",
"escape-string-regexp": "^5.0.0",
Expand Down
Loading