Useful MCP Tools to use with LLM Coding Agents
mcptools is a Model Context Protocol (MCP) server that exposes various tools for LLM agents to interact with external services. Currently provides tools for:
- Atlassian Jira: Search, create, update tickets, and saved queries (
jira_search,jira_create,jira_get,jira_update,jira_query_list,jira_query_save,jira_query_delete,jira_query_load) - Atlassian Confluence: Search pages using CQL (
confluence_search) - Atlassian Bitbucket: List and read pull requests with diff support (
bitbucket_pr_list,bitbucket_pr_read) - HackerNews: Access HN posts, comments, and stories (
hn_read_item,hn_list_items) - Web Scraping: Fetch web pages and convert to Markdown with CSS selector filtering, section extraction, and pagination (
md_fetch,md_toc) - PDF Navigation: Parse PDF documents into navigable trees, read sections, peek at content, and extract images (
pdf_toc,pdf_read,pdf_peek,pdf_images,pdf_image,pdf_info) - Strand: Generate Rust code via local Ollama model (
generate_code) - GrepRAG: Retrieve relevant code context from a repository using a local model + ripgrep + BM25 ranking (
greprag_retrieve) - UI Annotations: Query and manage UI annotations from a calendsync dev server (
ui_annotations_list,ui_annotations_get,ui_annotations_resolve,ui_annotations_clear)
# Build and install to ~/.local/bin
cargo xtask install
# Or specify a custom installation path
cargo xtask install --path /usr/local/binThe MCP server can run in two transport modes:
mcptools mcp stdioThis mode communicates via standard input/output, making it suitable for local LLM agents like Claude Desktop or other MCP clients that spawn server processes.
mcptools mcp sse --port 3000 --host 127.0.0.1This mode runs an HTTP server with Server-Sent Events (SSE) support, suitable for web-based clients.
Endpoints:
GET /sse- SSE endpoint for real-time updatesPOST /message- JSON-RPC endpoint for tool calls
Add to your Claude Desktop config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"mcptools": {
"command": "mcptools",
"args": ["mcp", "stdio"]
}
}
}Option 1: Using the claude mcp add command (recommended)
claude mcp add mcptools -- mcptools mcp stdioThis automatically adds the server to your Claude Code configuration.
Option 2: Manual configuration
Add to your Claude Code config file (~/Library/Application Support/Claude/claude_code_config.json on macOS, %APPDATA%\Claude\claude_code_config.json on Windows):
{
"mcpServers": {
"mcptools": {
"command": "mcptools",
"args": ["mcp", "stdio"]
}
}
}After adding the configuration, restart Claude Code for the changes to take effect. The mcptools will be available for use in your coding sessions.
Any MCP client can connect by spawning the process and communicating via JSON-RPC 2.0 over stdio:
mcptools mcp stdioSend JSON-RPC requests via stdin, receive responses via stdout.
Environment Variables: Each service supports its own credentials that override the shared ATLASSIAN_* variables:
- Jira:
JIRA_BASE_URL,JIRA_EMAIL,JIRA_API_TOKEN(fallback:ATLASSIAN_*) - Confluence:
CONFLUENCE_BASE_URL,CONFLUENCE_EMAIL,CONFLUENCE_API_TOKEN(fallback:ATLASSIAN_*) - Bitbucket:
BITBUCKET_USERNAME,BITBUCKET_APP_PASSWORD
For detailed setup instructions, see docs/ATLASSIAN_SETUP.md. For a quick start guide, see docs/ATLASSIAN_QUICK_START.md.
Search Jira issues using JQL (Jira Query Language).
Parameters:
query(string) - JQL query to search issues (e.g.,project = PROJ AND status = Open)queryName(string) - Name of a saved query to execute instead of providing raw JQLlimit(number, optional) - Maximum results to return (default: 10, max: 100)nextPageToken(string, optional) - Pagination token for fetching the next page
Example:
{
"method": "tools/call",
"params": {
"name": "jira_search",
"arguments": {
"query": "assignee = currentUser() AND status NOT IN (Done, Closed)",
"limit": 20
}
}
}Get detailed information about a specific Jira ticket.
Parameters:
issueKey(string, required) - Jira issue key (e.g.,PROJ-123)
Example:
{
"method": "tools/call",
"params": {
"name": "jira_get",
"arguments": {
"issueKey": "PROJ-123"
}
}
}Create a new Jira ticket.
Parameters:
summary(string, required) - Title/summary of the ticketdescription(string, optional) - Description of the ticketproject(string, optional) - Project key (default: PROD)issueType(string, optional) - Issue type (e.g., Bug, Story, Task)priority(string, optional) - Priority (e.g., High, Medium, Low)assignee(string, optional) - Assignee (email, display name, or "me")
Example:
{
"method": "tools/call",
"params": {
"name": "jira_create",
"arguments": {
"summary": "Fix login bug",
"description": "Users cannot log in with SSO",
"issueType": "Bug",
"priority": "High"
}
}
}Update fields on an existing Jira ticket.
Parameters:
ticketKey(string, required) - Ticket key (e.g., PROJ-123)status(string, optional) - New status (e.g., "In Progress", "Done")priority(string, optional) - New priorityissueType(string, optional) - New issue typeassignee(string, optional) - New assignee (email, display name, or "me")
Example:
{
"method": "tools/call",
"params": {
"name": "jira_update",
"arguments": {
"ticketKey": "PROJ-123",
"status": "In Progress",
"assignee": "me"
}
}
}List all saved Jira queries.
Parameters: None
Example:
{
"method": "tools/call",
"params": {
"name": "jira_query_list",
"arguments": {}
}
}Save a Jira JQL query with a name for later reuse.
Parameters:
name(string, required) - Name for the saved query (alphanumeric, hyphens, underscores only)query(string, required) - JQL query to saveupdate(boolean, optional) - If true, overwrites an existing query with the same name (default: false)
Example:
{
"method": "tools/call",
"params": {
"name": "jira_query_save",
"arguments": {
"name": "my-open-bugs",
"query": "project = PROJ AND type = Bug AND status != Done"
}
}
}Delete a saved Jira query by name.
Parameters:
name(string, required) - Name of the saved query to delete
Load and display the contents of a saved Jira query.
Parameters:
name(string, required) - Name of the saved query to load
Search Confluence pages using CQL (Confluence Query Language).
Parameters:
query(string, required) - CQL query to search pageslimit(number, optional) - Maximum results to return (default: 10)
Example:
{
"method": "tools/call",
"params": {
"name": "confluence_search",
"arguments": {
"query": "space = WIKI AND text ~ 'deployment'",
"limit": 10
}
}
}List pull requests for a Bitbucket repository.
Parameters:
repo(string, required) - Repository inworkspace/repo_slugformatstate(array, optional) - Filter by PR state(s): OPEN, MERGED, DECLINED, SUPERSEDEDlimit(number, optional) - Max results per page (default: 10)nextPage(string, optional) - Pagination URL for fetching the next page
Example:
{
"method": "tools/call",
"params": {
"name": "bitbucket_pr_list",
"arguments": {
"repo": "myworkspace/myrepo",
"state": ["OPEN"],
"limit": 20
}
}
}Read details of a specific Bitbucket pull request including diff, diffstat, and comments.
Parameters:
repo(string, required) - Repository inworkspace/repo_slugformatprNumber(number, required) - Pull request numberlimit(number, optional) - Max comments per page (default: 100)diffLimit(number, optional) - Max diffstat entries per page (default: 500)lineLimit(number, optional) - Truncate diff to N lines (default: 500, use -1 for unlimited)noDiff(boolean, optional) - Skip fetching diff content (default: false)
Example:
{
"method": "tools/call",
"params": {
"name": "bitbucket_pr_read",
"arguments": {
"repo": "myworkspace/myrepo",
"prNumber": 123,
"lineLimit": 200
}
}
}Note: The lineLimit parameter defaults to 500 lines to prevent overwhelming responses. Use lineLimit: -1 for the complete diff.
Read HackerNews posts and comments with pagination support.
Parameters:
item(string, required) - HackerNews item ID (e.g., "8863") or full URL (e.g., "https://news.ycombinator.com/item?id=8863")limit(number, optional) - Number of comments per page (default: 10)page(number, optional) - Page number, 1-indexed (default: 1)thread(string, optional) - Comment thread ID to read a specific comment thread
Example Usage:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "hn_read_item",
"arguments": {
"item": "8863",
"limit": 5,
"page": 1
}
}
}Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{\"id\":8863,\"title\":\"My YC app: Dropbox...\",\"comments\":[...],\"pagination\":{...}}"
}
]
}
}List HackerNews stories with pagination support.
Parameters:
story_type(string, optional) - Type of stories: "top", "new", "best", "ask", "show", "job" (default: "top")limit(number, optional) - Number of stories per page (default: 30)page(number, optional) - Page number, 1-indexed (default: 1)
Example Usage:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "hn_list_items",
"arguments": {
"story_type": "top",
"limit": 10,
"page": 1
}
}
}Fetch web pages using headless Chrome and convert to Markdown. Supports CSS selector filtering to extract specific page elements, character-based pagination, and section extraction using offsets from md_toc.
Parameters:
url(string, required) - URL of the web page to fetchtimeout(number, optional) - Timeout in seconds (default: 30)raw_html(boolean, optional) - Return raw HTML instead of Markdown (default: false)selector(string, optional) - CSS selector to filter content (e.g., "article", "main", "div.content")strategy(string, optional) - Selection strategy when multiple elements match: "first", "last", "all", "n" (default: "first")index(number, optional) - Index for "n" strategy (0-indexed)offset(number, optional) - Character offset to start from (default: 0). When provided, takes precedence overpage. Use with values frommd_tocto extract specific sectionslimit(number, optional) - Characters per page for pagination (default: 1000)page(number, optional) - Page number, 1-indexed (default: 1). Ignored ifoffsetis provided
Example Usage:
// Basic fetch with default pagination
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "md_fetch",
"arguments": {
"url": "https://docs.example.com/guide"
}
}
}
// Extract main content only
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "md_fetch",
"arguments": {
"url": "https://example.com",
"selector": "main"
}
}
}
// Get all article elements with custom pagination
{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "md_fetch",
"arguments": {
"url": "https://blog.example.com",
"selector": "article",
"strategy": "all",
"limit": 500,
"page": 2
}
}
}Response includes pagination metadata:
{
"url": "https://example.com",
"title": "Page Title",
"content": "...(paginated markdown content)...",
"pagination": {
"current_page": 1,
"total_pages": 23,
"total_characters": 22161,
"limit": 1000,
"has_more": true
}
}Extract table of contents from web pages by parsing markdown headings (H1-H6). Returns character offsets and limits for each section, enabling precise section extraction with md_fetch. Sections are defined as: heading + all content until the next same-or-higher-level heading.
Parameters:
url(string, required) - URL of the web page to fetchtimeout(number, optional) - Timeout in seconds (default: 30)selector(string, optional) - CSS selector to filter content (e.g., "article", "main")strategy(string, optional) - Selection strategy when multiple elements match: "first", "last", "all", "n" (default: "first")index(number, optional) - Index for "n" strategy (0-indexed)output(string, optional) - Output format: "indented", "markdown", "json" (default: "indented")
Example Usage:
// Get table of contents with section offsets
{
"jsonrpc": "2.0",
"id": 6,
"method": "tools/call",
"params": {
"name": "md_toc",
"arguments": {
"url": "https://docs.example.com/guide"
}
}
}Response:
{
"url": "https://docs.example.com/guide",
"title": "User Guide",
"entries": [
{
"level": 2,
"text": "Getting Started",
"char_offset": 0,
"char_limit": 1234
},
{
"level": 3,
"text": "Installation",
"char_offset": 156,
"char_limit": 580
},
{
"level": 2,
"text": "Advanced Usage",
"char_offset": 1234,
"char_limit": 2000
}
],
"fetch_time_ms": 1523
}Workflow: Extract Specific Sections
// Step 1: Get TOC to find sections
{
"method": "tools/call",
"params": {
"name": "md_toc",
"arguments": {"url": "https://docs.example.com"}
}
}
// Step 2: Use char_offset and char_limit to fetch specific section
{
"method": "tools/call",
"params": {
"name": "md_fetch",
"arguments": {
"url": "https://docs.example.com",
"offset": 156,
"limit": 580
}
}
}
// Returns only the "Installation" sectionEnvironment Variable: CALENDSYNC_DEV_URL — Base URL of the calendsync dev server (default: http://localhost:3000)
List all UI annotations from the calendsync dev server. Returns selector, component name, note, and resolution status for each annotation.
Parameters:
url(string, optional) — Dev server URL (overridesCALENDSYNC_DEV_URL)
Example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "ui_annotations_list",
"arguments": {}
}
}Get a single UI annotation by ID with full details including computed styles, bounding box, and optional screenshot.
Parameters:
id(string, required) — Annotation IDurl(string, optional) — Dev server URL (overridesCALENDSYNC_DEV_URL)
Example:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "ui_annotations_get",
"arguments": {
"id": "abc-123"
}
}
}Mark a UI annotation as resolved with a summary of the changes made.
Parameters:
id(string, required) — Annotation IDsummary(string, required) — Description of what was fixedurl(string, optional) — Dev server URL (overridesCALENDSYNC_DEV_URL)
Example:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "ui_annotations_resolve",
"arguments": {
"id": "abc-123",
"summary": "Increased font size to 24px for mobile"
}
}
}Clear all UI annotations from the dev server.
Parameters:
url(string, optional) — Dev server URL (overridesCALENDSYNC_DEV_URL)
Example:
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "ui_annotations_clear",
"arguments": {}
}
}Parse a PDF document and return its table of contents as a navigable tree with section IDs, headings, content previews, image counts, and page ranges.
Parameters:
path(string, required) - Absolute path to the PDF file
Example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "pdf_toc",
"arguments": {
"path": "/absolute/path/to/document.pdf"
}
}
}Read section content as rendered Markdown with image references. Omit sectionId to read the entire document.
Parameters:
path(string, required) - Absolute path to the PDF filesectionId(string, optional) - Section ID frompdf_toc(e.g.,s-1-0). Omit for whole document.
Example:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "pdf_read",
"arguments": {
"path": "/absolute/path/to/document.pdf",
"sectionId": "s-1-0"
}
}
}Sample a text snippet from a section without reading the full content. Returns the snippet, position, and total character count.
Parameters:
path(string, required) - Absolute path to the PDF filesectionId(string, optional) - Section ID frompdf_toc. Omit for whole document.position(string, optional) - Where to sample: "beginning" (default), "middle", "ending", "random"limit(number, optional) - Maximum characters to return (default: 500)
Example:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "pdf_peek",
"arguments": {
"path": "/absolute/path/to/document.pdf",
"sectionId": "s-1-0",
"position": "middle",
"limit": 300
}
}
}List images in a section or the entire document. Returns image IDs, formats, and alt text.
Parameters:
path(string, required) - Absolute path to the PDF filesectionId(string, optional) - Section ID frompdf_toc. Omit for all images.
Example:
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "pdf_images",
"arguments": {
"path": "/absolute/path/to/document.pdf",
"sectionId": "s-1-0"
}
}
}Extract a specific image by ID or pick a random one. Returns base64-encoded image data with format and size.
Parameters:
path(string, required) - Absolute path to the PDF fileimageId(string, optional) - Image ID (XObject name). Required unlessrandomis true.sectionId(string, optional) - Section ID to scope image selection (used withrandom)random(boolean, optional) - Pick a random image. Cannot be used withimageId.
Example:
{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "pdf_image",
"arguments": {
"path": "/absolute/path/to/document.pdf",
"imageId": "Im1"
}
}
}Get document metadata including title, author, page count, and creator.
Parameters:
path(string, required) - Absolute path to the PDF file
Example:
{
"jsonrpc": "2.0",
"id": 6,
"method": "tools/call",
"params": {
"name": "pdf_info",
"arguments": {
"path": "/absolute/path/to/document.pdf"
}
}
}Generate Rust code via a local Ollama model. The model outputs raw Rust code without markdown fences or explanations.
Parameters:
instruction(string, required) - What code to generatecontext(string, optional) - Additional context for code generationfiles(array of strings, optional) - File paths to include as contextollama_url(string, optional) - Ollama API base URL (default:http://localhost:11434)model(string, optional) - Model name (default:maternion/strand-rust-coder)system_prompt(string, optional) - Optional system prompt to override the model's default behavior
Example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "generate_code",
"arguments": {
"instruction": "Write a function that adds two numbers",
"files": ["src/lib.rs", "src/types.rs"]
}
}
}Retrieve relevant code context from a repository. Uses a local Ollama model to generate regex patterns from a code snippet, executes them as ripgrep commands, ranks results with BM25, merges overlapping snippets, and returns the top results within a token budget.
Parameters:
local_context(string, required) - The code snippet to find cross-file references forrepo_path(string, optional) - Path to the repository to search (default:.)token_budget(integer, optional) - Maximum token budget for returned context (default:4096)ollama_url(string, optional) - Ollama API base URL (default:http://localhost:11434)model(string, optional) - Model name for query generation (default:greprag)
Example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "greprag_retrieve",
"arguments": {
"local_context": "let code = extract_code(&response);",
"repo_path": "./my-project",
"token_budget": 2048
}
}
}Requires: A running Ollama instance with the greprag model. See docs/GREPRAG_SETUP.md for setup instructions.
This server implements the Model Context Protocol specification with the following methods:
Establishes connection and returns server capabilities.
Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {}
}Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {}
},
"serverInfo": {
"name": "mcptools",
"version": "0.0.0"
}
}
}Returns list of available tools.
Request:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}Response:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "hn_read_item",
"description": "Read a HackerNews post and its comments...",
"inputSchema": {
"type": "object",
"properties": {
"item": {
"type": "string",
"description": "HackerNews item ID or URL"
},
"limit": {
"type": "number",
"description": "Number of comments per page (default: 10)"
},
"page": {
"type": "number",
"description": "Page number, 1-indexed (default: 1)"
},
"thread": {
"type": "string",
"description": "Comment thread ID to read (optional)"
}
},
"required": ["item"]
}
}
]
}
}Executes a specific tool.
Request:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "hn_read_item",
"arguments": {
"item": "8863",
"limit": 2
}
}
}Response:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "{\"id\":8863,\"title\":\"My YC app: Dropbox - Throw away your USB drive\",\"url\":\"http://www.getdropbox.com/u/2/screencast.html\",\"author\":\"dhouston\",\"score\":104,\"time\":\"2007-04-04 19:16:40 UTC\",\"text\":null,\"total_comments\":71,\"comments\":[{\"id\":9224,\"author\":\"BrandonM\",\"time\":\"2007-04-05 15:16:54 UTC\",\"text\":\"I have a few qualms with this app...\",\"replies_count\":1},{\"id\":8917,\"author\":\"brett\",\"time\":\"2007-04-04 21:48:13 UTC\",\"text\":\"This is genius...\",\"replies_count\":0}],\"pagination\":{\"current_page\":1,\"total_pages\":17,\"total_comments\":33,\"limit\":2,\"next_page_command\":\"mcptools hn read 8863 --page 2\",\"prev_page_command\":null}}"
}
]
}
}Start the server:
mcptools mcp sse --port 3000Test the endpoints:
# Initialize
curl -X POST http://127.0.0.1:3000/message \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
# List tools
curl -X POST http://127.0.0.1:3000/message \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
# Call hn_read_item tool
curl -X POST http://127.0.0.1:3000/message \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"hn_read_item","arguments":{"item":"8863","limit":2}}}'You can also use the tools directly via CLI without running an MCP server.
# Search for issues assigned to you
mcptools atlassian jira search "assignee = currentUser() AND status NOT IN (Done, Closed)"
# Search with limit
mcptools atlassian jira search "project = PROJ AND status = Open" --limit 20
# Get ticket details
mcptools atlassian jira get PROJ-123
# Create a new ticket
mcptools atlassian jira create --summary "Fix bug" --description "Details..." --issue-type Bug
# Update a ticket
mcptools atlassian jira update PROJ-123 --status "In Progress" --assignee me
# List custom field values
mcptools atlassian jira fields --project PROJ
# Output as JSON
mcptools atlassian jira search "project = PROJ" --json
# Save a query
mcptools atlassian jira search 'project = "PM" AND status = Open' --save --query devops
# Execute a saved query
mcptools atlassian jira search --query devops
# List all saved queries
mcptools atlassian jira search --list
# View query contents
mcptools atlassian jira search --load --query devops
# Update existing query
mcptools atlassian jira search 'project = "PM"' --save --query devops --update
# Delete a query
mcptools atlassian jira search --delete --query devops# Search for pages
mcptools atlassian confluence search "text ~ 'deployment'"
# Search in a specific space
mcptools atlassian confluence search "space = WIKI AND text ~ 'api'" --limit 10
# Output as JSON
mcptools atlassian confluence search "text ~ 'guide'" --json# List open PRs in a repository
mcptools atlassian bitbucket pr list --repo "myworkspace/myrepo"
# Filter by state
mcptools atlassian bitbucket pr list --repo "myworkspace/myrepo" --state OPEN --state MERGED
# Read PR details with diff
mcptools atlassian bitbucket pr read --repo "myworkspace/myrepo" 123
# Skip diff content
mcptools atlassian bitbucket pr read --repo "myworkspace/myrepo" 123 --no-diff
# Limit diff output to 200 lines
mcptools atlassian bitbucket pr read --repo "myworkspace/myrepo" 123 --line-limit 200
# Only show diff (skip details and comments)
mcptools atlassian bitbucket pr read --repo "myworkspace/myrepo" 123 --diff-only# Read a post with default settings (10 comments)
mcptools hn read 8863
# Read with custom limit
mcptools hn read 8863 --limit 5
# Navigate to specific page
mcptools hn read 8863 --page 2
# Read specific comment thread
mcptools hn read 8863 --thread 9224
# Output as JSON
mcptools hn read 8863 --json
# Use full URL instead of ID
mcptools hn read "https://news.ycombinator.com/item?id=8863"
# List stories
mcptools hn list --story-type top --limit 20# Basic fetch (converts to Markdown)
mcptools md fetch https://example.com
# With CSS selector to extract specific content
mcptools md fetch https://docs.example.com --selector "main"
mcptools md fetch https://example.com --selector "article.post"
# With pagination (1000 characters per page by default)
mcptools md fetch https://example.com --page 2
mcptools md fetch https://example.com --limit 500 --page 1
# Extract specific section using offset (from md toc)
mcptools md fetch https://docs.example.com --offset 1234 --limit 580
# Selection strategies for multiple matches
mcptools md fetch https://example.com --selector "article" --strategy all
mcptools md fetch https://example.com --selector "article" --strategy last
mcptools md fetch https://example.com --selector "p" --strategy n --index 2
# Get raw HTML instead of Markdown
mcptools md fetch https://example.com --raw-html
# Output as JSON
mcptools md fetch https://example.com --selector "main" --json
# Combine features
mcptools md fetch https://docs.example.com --selector "main" --limit 1000 --page 1 --json# Get TOC with default indented format (shows offset/limit for each section)
mcptools md toc https://docs.example.com
# Get TOC as markdown list
mcptools md toc https://example.com --output markdown
# Get TOC as JSON (includes char_offset and char_limit)
mcptools md toc https://example.com --json
# Extract TOC from specific page section
mcptools md toc https://docs.example.com --selector "main"
mcptools md toc https://example.com --selector "article" --strategy first
# Complete workflow: Get TOC, then fetch specific section
mcptools md toc https://docs.example.com --json > toc.json
# Use char_offset and char_limit from toc.json
mcptools md fetch https://docs.example.com --offset 1234 --limit 580# Get document table of contents
mcptools pdf toc document.pdf
# Read a specific section
mcptools pdf read document.pdf s-1-0
# Read the whole document
mcptools pdf read document.pdf
# Peek at a section (quick preview)
mcptools pdf peek document.pdf s-1-0
# Peek at middle of document with custom limit
mcptools pdf peek document.pdf --position middle --limit 300
# List all images in the document
mcptools pdf images document.pdf
# List images in a specific section
mcptools pdf images document.pdf s-1-0
# Extract an image by ID
mcptools pdf image document.pdf Im1 --output photo.jpg
# Pick a random image
mcptools pdf image document.pdf --random
# Random image from a specific section
mcptools pdf image document.pdf --random --section s-1-0
# Get document metadata
mcptools pdf info document.pdf# Basic code generation
mcptools strand generate "Write a function that adds two numbers"
# With file context
mcptools strand generate "Add error handling" --files src/lib.rs src/types.rs
# Custom model/URL
mcptools strand generate "Write a hello world" \
--model codellama \
--ollama-url http://localhost:11434# Retrieve code context for a snippet
mcptools grep-rag retrieve "self.deck.draw()" --repo-path ./my-project
# With custom token budget
mcptools grep-rag retrieve "fn process(input: &str)" \
--repo-path ./src \
--token-budget 2048
# Custom model/URL
mcptools grep-rag retrieve "let result = parse(&input);" \
--repo-path . \
--model greprag \
--ollama-url http://localhost:11434Environment Variables:
| Variable | Default | Description |
|---|---|---|
OLLAMA_URL |
http://localhost:11434 |
Ollama API base URL |
GREPRAG_MODEL |
greprag |
Default model name |
Requires: A running Ollama instance with the greprag model. See docs/GREPRAG_SETUP.md for setup instructions.
When using md_toc and md_fetch with Claude Code or other LLM coding agents, follow this workflow to efficiently extract web content:
Step 1: Understand page structure with md_toc
Always start by fetching the table of contents to understand the page layout and identify which sections contain the information you need:
mcptools md toc https://docs.example.comThis returns a hierarchical list of sections with character offsets and limits, allowing you to precisely target content.
Step 2: Fetch targeted content with md_fetch
After analyzing the TOC, use character offsets to extract specific sections:
# Fetch a specific section using offset and limit from md_toc
mcptools md fetch https://docs.example.com --offset 1234 --limit 580Or use CSS selectors to filter content:
# Extract main content only
mcptools md fetch https://docs.example.com --selector "main"- Always use
md_tocfirst - This helps you understand page structure before fetching, reducing unnecessary content extraction - Use CSS selectors - Narrow down to specific page sections (e.g.,
main,article,div.content) to avoid noise from sidebars and navigation - Leverage pagination - For large pages, use the
limitandpageparameters or character offsets to fetch content in manageable chunks - Site-specific selectors:
- LocalStack Documentation (
https://docs.localstack.cloud/*): Useselector: "main"to get main content
- LocalStack Documentation (
- Combine tools efficiently - Use
md_tocto get metadata, thenmd_fetchwith precise offsets for targeted extraction
# Step 1: Get page structure
mcptools md toc https://docs.example.com --json
# Step 2: Use the returned metadata to fetch specific sections
# If the JSON shows an "Installation" section with char_offset: 156, char_limit: 580
mcptools md fetch https://docs.example.com --offset 156 --limit 580
# Alternative: Use CSS selectors for simpler cases
mcptools md fetch https://docs.example.com --selector "main" --limit 1000This approach ensures Claude Code gets focused, relevant content without unnecessary overhead.
Upgrade mcptools to the latest version.
# Upgrade to the latest version
mcptools upgrade
# Force upgrade even if already on latest
mcptools upgrade --force# Build
cargo build
# Run tests
cargo test
# Run clippy
cargo clippy
# Watch mode (requires bacon)
baconMIT