TOOL_FLOW_EXPLANATION.md•9.55 kB
# Tool Flow Explanation: `list_commits`
This document explains the complete flow of the `list_commits` tool from request to response.
## Complete Flow Diagram
```
User/Client
↓
HTTP POST Request (JSON-RPC)
↓
Express Server (mcp-server.ts)
↓
MCP Protocol Handler
↓
Tool Router
↓
listCommits Function (githubTools.ts)
↓
Octokit SDK (@octokit/rest)
↓
GitHub REST API
↓
Response Processing
↓
MCP Response Format
↓
HTTP Response (JSON)
↓
User/Client
```
## Step-by-Step Flow
### Step 1: Client Sends Request
**User executes:**
```bash
curl -X POST http://localhost:3001/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "list_commits",
"arguments": {
"repoOwner": "sadaf987",
"repoName": "github_sdk",
"branch": "main",
"perPage": 10
}
},
"id": 2
}'
```
**What happens:**
- HTTP POST request sent to `http://localhost:3001/mcp`
- Request body contains JSON-RPC 2.0 formatted message
- Headers include `Content-Type: application/json`
---
### Step 2: Express Server Receives Request
**Location:** `src/mcp-server.ts` (line 41)
```typescript
app.post('/mcp', async (req, res) => {
console.log('📥 MCP Request:', JSON.stringify(req.body, null, 2));
const { method, params, id } = req.body;
// ...
});
```
**What happens:**
- Express.js receives the HTTP POST request
- `express.json()` middleware parses JSON body
- Request logged to console for debugging
- Extracts `method`, `params`, and `id` from request body
**At this point:**
- `method` = `"tools/call"`
- `params` = `{ name: "list_commits", arguments: {...} }`
- `id` = `2`
---
### Step 3: MCP Protocol Routing
**Location:** `src/mcp-server.ts` (line 221)
```typescript
if (method === 'tools/call') {
const { name, arguments: toolArguments } = params;
const tool = name in tools ? tools[name as keyof typeof tools] : undefined;
// ...
}
```
**What happens:**
- Checks if method is `tools/call`
- Extracts tool name: `"list_commits"`
- Extracts arguments: `{ repoOwner: "sadaf987", repoName: "github_sdk", branch: "main", perPage: 10 }`
- Looks up tool in `tools` object
**Tool lookup:**
```typescript
const tools = {
mark_attendance: markAttendance,
commit_changes: commitChanges,
get_repo_info: getRepoInfo,
create_branch: createBranch,
list_branches: listBranches,
get_file_contents: getFileContents,
list_commits: listCommits, // ← Found here!
};
```
**Result:** `tool` = `listCommits` function
---
### Step 4: Tool Function Execution
**Location:** `src/tools/githubTools.ts` (line 282)
```typescript
export const listCommits = async ({
repoOwner,
repoName,
branch,
perPage,
}: {
repoOwner: string;
repoName: string;
branch?: string;
perPage?: number;
}) => {
try {
// ...
}
};
```
**What happens:**
- Function receives arguments:
- `repoOwner` = `"sadaf987"`
- `repoName` = `"github_sdk"`
- `branch` = `"main"`
- `perPage` = `10`
---
### Step 5: GitHub API Call via Octokit
**Location:** `src/tools/githubTools.ts` (line 294)
```typescript
const response = await octokit.repos.listCommits({
owner: repoOwner, // "sadaf987"
repo: repoName, // "github_sdk"
...(branch && { sha: branch }), // sha: "main"
per_page: perPage || 10, // per_page: 10
});
```
**What happens:**
- Octokit SDK makes HTTP request to GitHub API
- **Endpoint:** `GET https://api.github.com/repos/sadaf987/github_sdk/commits?sha=main&per_page=10`
- **Authentication:** Uses token from `process.env.GITHUB_PERSONAL_ACCESS_TOKEN`
- **Headers:** Octokit automatically adds:
- `Authorization: token YOUR_TOKEN`
- `Accept: application/vnd.github.v3+json`
- `User-Agent: octokit-rest.js/x.x.x`
**Octokit SDK handles:**
- HTTP request construction
- Authentication headers
- Error handling
- Response parsing
---
### Step 6: GitHub API Processes Request
**What happens on GitHub's side:**
- Validates authentication token
- Checks repository access permissions
- Retrieves commits from `main` branch
- Returns up to 10 commits (per_page=10)
- Formats response as JSON
**GitHub API Response:**
```json
{
"data": [
{
"sha": "cac8731aed5c16821729b600f05c890a2c6fc0cd",
"commit": {
"message": "Test commit from MCP",
"author": {
"name": "Sadaf987",
"date": "2025-11-12T08:52:39Z"
}
},
"html_url": "https://github.com/Sadaf987/test_MCP/commit/cac8731..."
},
// ... more commits
]
}
```
---
### Step 7: Response Processing
**Location:** `src/tools/githubTools.ts` (line 301)
```typescript
const commits = response.data.map((commit) => ({
sha: commit.sha.substring(0, 7), // "cac8731"
message: commit.commit.message.split('\n')[0], // First line only
author: commit.commit.author?.name || 'Unknown',
date: commit.commit.author?.date || 'Unknown',
url: commit.html_url,
}));
const commitList = commits
.map(
(c) =>
`- ${c.sha} - ${c.message}\n Author: ${c.author} | Date: ${c.date}\n URL: ${c.url}`
)
.join('\n\n');
```
**What happens:**
- Transforms GitHub API response into readable format
- Extracts relevant fields (SHA, message, author, date, URL)
- Formats as text string
- Shortens SHA to 7 characters for readability
---
### Step 8: MCP Response Format
**Location:** `src/tools/githubTools.ts` (line 316)
```typescript
return {
content: [
{
type: 'text',
text: `Recent commits in ${repoOwner}/${repoName}${branch ? ` (branch: ${branch})` : ''}:\n\n${commitList}\n\nTotal: ${commits.length} commit${commits.length !== 1 ? 's' : ''} shown`,
},
],
};
```
**What happens:**
- Formats response in MCP protocol format
- Returns object with `content` array
- Each content item has `type: 'text'` and `text` field
- Includes formatted commit list and summary
**Response structure:**
```typescript
{
content: [
{
type: 'text',
text: 'Recent commits in sadaf987/github_sdk (branch: main):\n\n- cac8731 - Test commit...\n\nTotal: 9 commits shown'
}
]
}
```
---
### Step 9: MCP Server Wraps Response
**Location:** `src/mcp-server.ts` (line 227)
```typescript
if (tool) {
try {
const result = await tool(toolArguments); // ← listCommits result
res.json({ jsonrpc: '2.0', result, id }); // ← Wraps in JSON-RPC format
} catch (error) {
// Error handling
}
}
```
**What happens:**
- Receives result from `listCommits` function
- Wraps in JSON-RPC 2.0 format
- Adds `jsonrpc: '2.0'` and `id: 2` (from original request)
**Final response:**
```json
{
"jsonrpc": "2.0",
"result": {
"content": [
{
"type": "text",
"text": "Recent commits in sadaf987/test_MCP..."
}
]
},
"id": 2
}
```
---
### Step 10: HTTP Response Sent to Client
**What happens:**
- Express.js sends HTTP response
- Status code: `200 OK`
- Content-Type: `application/json`
- Body: JSON-RPC formatted response
**Client receives:**
```json
{
"jsonrpc": "2.0",
"result": {
"content": [
{
"type": "text",
"text": "Recent commits in sadaf987/test_MCP (branch: main):\n\n- cac8731 - Test commit from MCP\n Author: Sadaf987 | Date: 2025-11-12T08:52:39Z\n URL: https://github.com/Sadaf987/test_MCP/commit/cac8731...\n\n...\n\nTotal: 9 commits shown"
}
]
},
"id": 2
}
```
---
## Key Components in the Flow
### 1. **Express Server** (`mcp-server.ts`)
- Receives HTTP requests
- Routes to appropriate handlers
- Formats JSON-RPC responses
### 2. **Tool Registry** (`tools` object)
- Maps tool names to functions
- Enables dynamic tool lookup
### 3. **Tool Function** (`listCommits` in `githubTools.ts`)
- Contains business logic
- Calls GitHub API via Octokit
- Transforms and formats response
### 4. **Octokit SDK** (`@octokit/rest`)
- Handles GitHub API communication
- Manages authentication
- Provides typed API methods
### 5. **GitHub REST API**
- External service
- Provides repository data
- Requires authentication
---
## Error Handling Flow
If an error occurs at any step:
1. **GitHub API Error:**
```typescript
catch (error) {
const message = error instanceof Error ? error.message : String(error);
return {
content: [{ type: 'text', text: `Failed to list commits: ${message}` }]
};
}
```
2. **Tool Not Found:**
```typescript
if (!tool) {
res.json({
jsonrpc: '2.0',
error: { code: -32601, message: 'Method not found' },
id
});
}
```
3. **Server Error:**
```typescript
catch (error) {
res.json({
jsonrpc: '2.0',
error: { code: -32000, message },
id
});
}
```
---
## Summary
**Request Flow:**
1. Client → HTTP POST → Express Server
2. Express → MCP Router → Tool Lookup
3. Tool Function → Octokit SDK → GitHub API
4. GitHub API → Response → Tool Function
5. Tool Function → Format → MCP Response
6. MCP Server → JSON-RPC Wrap → HTTP Response
7. HTTP Response → Client
**Key Points:**
- ✅ **MCP Protocol**: Standardized JSON-RPC 2.0 format
- ✅ **Tool Registration**: Dynamic lookup from `tools` object
- ✅ **GitHub SDK**: Octokit handles API communication
- ✅ **Error Handling**: Graceful error responses at each level
- ✅ **Response Format**: Consistent MCP `content` array format
This same flow applies to all tools - only the tool function and API endpoint change!