A custom AI agent built with the Claude Agent SDK featuring OAuth authentication, custom tools, and streaming chat interface.
- OAuth Authentication: Uses Claude subscription instead of API keys
- OpenAI-Compatible API: REST API server with streaming support
- Custom MCP Tools: Coffee shop price calculator tool
- Streaming Chat: Interactive CLI with color-coded output
- File Operations: Read, write, edit files in your project
- Tool Permissions: Granular control over allowed tools
- Node.js 18+
- pnpm
- Claude subscription (no API key needed)
pnpm installThe agent uses OAuth authentication automatically from your Claude Code CLI setup.
First time setup:
If you haven't used Claude Code CLI before, authenticate first:
# Install Claude Code CLI globally (if not already installed)
npm install -g @anthropic-ai/claude-code
# Login via OAuth
claude loginThis opens a browser window to authenticate with your Claude account. Once authenticated, you can use this custom agent.
No API key needed! The SDK automatically uses your Claude Code CLI authentication.
Run the interactive chat agent:
pnpm devOnce running, you can:
- Ask questions
- Request file operations
- Use the custom coffee price calculator tool
- Type
exitto quit
How many files are in this project?
What is the price of a medium oat milk latte?
Read the package.json file
Run the OpenAI-compatible API server:
# Development mode (auto-reload on changes)
pnpm api:dev
# Production mode
pnpm apiThe server runs on port 8130 by default (configurable in .env).
Update your .env file:
PORT=8130
API_KEY=your-secret-api-key # Change this to a secure key!- POST
/v1/chat/completions- OpenAI-compatible chat completions - GET
/health- Health check endpoint
Non-Streaming Request (Recommended):
curl http://localhost:8130/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-secret-api-key" \
-d '{
"model": "custom-claude-agent",
"messages": [
{"role": "user", "content": "What files are in this project?"}
]
}' | jq -r '.choices[0].message.content'Streaming Request:
curl http://localhost:8130/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-secret-api-key" \
-d '{
"model": "custom-claude-agent",
"messages": [
{"role": "user", "content": "What files are in this project?"}
],
"stream": true
}' | grep "^data: " | sed 's/^data: //' | grep -v "\[DONE\]" | jq -r '.choices[0].delta.content // empty'With System Message:
curl http://localhost:8130/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-secret-api-key" \
-d '{
"model": "custom-claude-agent",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the price of a large latte?"}
]
}' | jq -r '.choices[0].message.content'Python:
from openai import OpenAI
client = OpenAI(
api_key="your-secret-api-key",
base_url="http://localhost:8130/v1"
)
response = client.chat.completions.create(
model="custom-claude-agent",
messages=[
{"role": "user", "content": "What files are in this project?"}
]
)
print(response.choices[0].message.content)JavaScript/TypeScript:
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'your-secret-api-key',
baseURL: 'http://localhost:8130/v1'
});
const response = await client.chat.completions.create({
model: 'custom-claude-agent',
messages: [
{ role: 'user', content: 'What is the price of a large oat milk latte?' }
]
});
console.log(response.choices[0].message.content);The agent includes a custom MCP tool for calculating coffee prices:
- Tool:
calculate_coffee_price - Inputs: size, drink type, extras, currency
- Example: "What's the price of a large latte with oat milk?"
Edit src/index.ts to modify which tools the agent can use:
allowedTools: ['Read', 'Glob', 'Bash', 'Grep', `mcp__${customServer.name}__*`]Customize the agent's behavior by editing the customSystemPrompt in src/index.ts.
Add new tools in src/tools.ts using the tool() function:
const myTool = tool({
name: 'my_tool',
description: 'What this tool does',
inputSchema: z.object({
// Define inputs with Zod
}),
handler: async (input) => {
// Tool implementation
return result;
}
});pnpm dev- Run the CLI agent in development modepnpm api- Run the API serverpnpm api:dev- Run the API server in watch mode (auto-reload)pnpm build- Build TypeScript to JavaScriptpnpm start- Run the built CLI agent
src/index.ts- Main agent with CLI interfacesrc/api-server.ts- OpenAI-compatible REST API serversrc/tools.ts- Custom MCP tools and server definitionsrc/config.ts- Configuration managementsrc/hooks.ts- Hook execution systemtsconfig.json- TypeScript configuration.env- Environment variables (API key, port, etc.)
ISC