granola-mcp
mcp-template
A starter template for building MCP (Model Context Protocol) servers with the dedalus_mcp framework. Authentication is handled by DAuth (Dedalus Auth).
This template supports three auth frameworks — No Auth, API Key, and OAuth. Each has its own src-* folder with a complete, ready-to-run server. You can either use the CLI to scaffold a new project automatically, or clone this repo and rename a folder manually.
What is DAuth?
DAuth is a multi-tenant authentication layer for MCP servers built by Dedalus Labs. It solves a core problem in the MCP ecosystem: most servers require API keys or tokens, but the MCP spec doesn't define how non-OAuth credentials should be handled securely. Without DAuth, developers either build their own auth infrastructure or pass raw secrets around — both are bad options.
DAuth is zero-trust and host-blind — Dedalus never sees your raw API keys. Here's how it works:
The SDK encrypts credentials client-side before they leave your device.
When a request reaches your MCP server, it acts as a standard OAuth 2.1 Resource Server — access is verified without touching the credential.
Authenticated requests are forwarded to the Enclave, a network-isolated, hardware-secured execution environment written in Rust.
Inside the Enclave, the credential is decrypted for milliseconds, used to call the external API, then zeroed from memory.
Only the API response is returned — the raw secret is never exposed to your server code, to Dedalus, or to the network.
This means your MCP server only holds an opaque connection handle, never a raw key. DAuth is built into the dedalus_mcp SDK and works across all auth types (Bearer tokens, API keys, OAuth, etc.).
Related MCP server: Streamable HTTP Python MCP Server Template
Quick Start
Option A: CLI (recommended)
Scaffold a new project with one command. The CLI prompts for your project name, auth type, and package manager, then generates a ready-to-run project with dependencies installed.
npx create-dmcpOr pass the project name directly:
npx create-dmcp my-mcp-serverRequires Node.js >= 18. The generated project is pure Python.
Option B: Clone and rename
Clone this repo and rename the src-* folder that matches your auth type:
git clone https://github.com/NickyHeC/mcp-template.git my-mcp-server
cd my-mcp-server
mv src-api-key src
rm -rf src-no-auth src-oauth
pip install -e .Project Structure
project-root/
├── cli/ # CLI scaffolding tool (npx create-dmcp)
│ └── index.ts
├── src-no-auth/ # No Auth — self-contained tools, no credentials
│ ├── main.py
│ ├── tools.py
│ └── client.py
├── src-api-key/ # API Key — static credential via DAuth
│ ├── main.py
│ ├── tools.py
│ └── client.py
├── src-oauth/ # OAuth — browser-based auth via DAuth
│ ├── main.py
│ ├── tools.py
│ └── client.py
├── pyproject.toml # Python dependencies and build config
├── package.json # Node.js config for the CLI
├── tsconfig.json # TypeScript config for the CLI
├── .env.example # Environment variable reference (per auth type)
├── PROJECT.md # Platform research notepad (for you / your AI agent)
├── LICENSE
└── README.mdEach src-* folder is a complete, self-contained server. If using the CLI, it copies the right template into <project>/src/ automatically. If cloning manually, rename the folder you want:
mv src-api-key src # rename your chosen template to src/The server code expects to live in a folder called src/ — all internal imports use from src.tools import ... and from src.main import .... After renaming (or CLI scaffolding), the server is ready to configure and run.
Choose Your Auth Framework
Pick the framework that matches your target platform's authentication method.
Framework | When to use | Folder |
No Auth | Tools that don't call external APIs — calculators, formatters, local utilities |
|
API Key | Platforms that use static credentials — API keys, personal access tokens, bot tokens (e.g. GitHub, Slack, Discord) |
|
OAuth | Platforms that require browser-based user authorization — OAuth 2.0 flows (e.g. Gmail, Linear, Spotify, Google Calendar) |
|
No Auth
Use when your tools are self-contained and don't need to call any external API.
No
Connectionobject neededNo DAuth configuration
No environment variables beyond basic server settings
Tools are simple decorated functions
from dedalus_mcp import MCPServer, tool
@tool(description="Add two numbers")
def add(a: float, b: float) -> float:
return a + b
server = MCPServer("my-mcp")
server.collect(add)To use: mv src-no-auth src
API Key
Use when the platform authenticates with a static credential that the user provides once (API key, personal access token, bot token, etc.).
Connection+SecretKeysdeclares the credential nameDAuth encrypts and manages the credential in its enclave
Tools can use
ctx.dispatch()for authenticated requests, or call APIs directlyEnvironment variables:
DEDALUS_AS_URL, your platform's token
from dedalus_mcp.auth import Connection, SecretKeys
platform_connection = Connection(
name="github",
secrets=SecretKeys(token="GITHUB_TOKEN"),
base_url="https://api.github.com",
auth_header_format="token {api_key}",
)To use: mv src-api-key src
OAuth
Use when the platform requires a browser-based OAuth flow where users authorize your application to act on their behalf.
Connection+SecretKeysdeclares the token name (same as API Key from code perspective)The Dedalus platform handles the full OAuth token exchange externally
OAuth configuration (client ID, client secret, authorize/token URLs, scopes) is set via environment variables
Important: OAuth environment variables must be baked into the server when deploying to ensure the connection works
Tools use
ctx.dispatch()for authenticated requests through the DAuth enclave
from dedalus_mcp.auth import Connection, SecretKeys
platform_connection = Connection(
name="linear-mcp",
secrets=SecretKeys(token="LINEAR_ACCESS_TOKEN"),
base_url="https://api.linear.app",
auth_header_format="Bearer {api_key}",
)Note on OAuth with DAuth: Your Python server code looks nearly identical to the API Key template. The difference is that the Dedalus platform reads the
OAUTH_*environment variables to orchestrate the browser-based OAuth flow and token refresh. Your server code never manages OAuth tokens directly — it just callsctx.dispatch()and DAuth applies the token inside the enclave.
To use: mv src-oauth src
How to Build an MCP Server from This Template
If you used the CLI (
npx create-dmcp), steps 2 is already done — the CLI chose the template, renamed it tosrc/, and installed dependencies. You still need to fill in.env(step 3) and configure the server (step 4).
1. Research the Target Platform API
Read the API docs for the platform you want to integrate. Note:
Available endpoints and features
Authentication method (Bearer token, API key, OAuth, etc.)
Rate limits and restrictions
Response formats
Save your notes in PROJECT.md — it serves as context for you and for AI coding agents in later steps. The file is pre-formatted with sections for all the information you'll need.
Tip: Once your PROJECT.md is filled in, you can hand the project off to an AI coding agent with a prompt like: "Build my MCP server based on this template and the notes in PROJECT.md." The agent can read the template files, your research notes, and this README to implement the full server with minimal back-and-forth.
2. Choose an Auth Framework and Rename the Folder
Skip this step if you used the CLI — it already did this for you.
Based on your research, pick the right auth framework from the table above. Rename the chosen folder to src/ and remove the others:
# Example: using the OAuth template
mv src-oauth src
rm -rf src-no-auth src-api-key3. Set Up Environment Variables
Skip cp if you used the CLI — .env.example is already in your project.
cp .env.example .envFill in only the variables for your chosen auth framework. See .env.example for which variables belong to which framework.
No Auth: No environment variables needed.
API Key: Set
DEDALUS_AS_URLand your platform's token (e.g.GITHUB_TOKEN).OAuth: Set
DEDALUS_AS_URL,DEDALUS_API_KEY, and allOAUTH_*variables. These must also be configured in the deployment environment.
4. Configure the Server (src/main.py)
Customize main.py with your platform's details:
Connection name — Change
"platform"to your platform's identifier (e.g."github","linear","spotify").Secret key — Update
SecretKeys(token="...")to match your credential name. The API Key template uses"API_TOKEN"; the OAuth template uses"ACCESS_TOKEN". Rename to match your platform (e.g."GITHUB_TOKEN","LINEAR_ACCESS_TOKEN").Base URL — Set to the platform's API root (e.g.
"https://api.github.com").Auth header format — Set how the credential is attached. Common formats:
"Bearer {api_key}","token {api_key}","Bot {api_key}".Server name — Change
"my-mcp"to something descriptive (e.g."github-mcp"). The CLI does this automatically.
5. Implement Tools (src/tools.py)
Define the tools your server will expose:
Result models — Create Pydantic
BaseModelsubclasses for structured return values.Request helper — For API Key and OAuth templates, use the
api_request()helper (which wrapsctx.dispatch()) to make authenticated calls through DAuth.Tool functions — Decorate functions with
@tool(description="..."). Use type hints for parameters and return a Pydantic model.Tool registry — Add every tool to the
toolslist at the bottom of the file.
The template files include example tools demonstrating each pattern.
6. Test Locally
Install dependencies:
pip install -e .Test your connection first (API Key and OAuth only). Before starting the server, verify that your Connection config and credentials actually work:
python -m src.client --test-connectionThis uses ConnectionTester from dedalus_mcp.testing to make a real API call to your target platform — no running server needed. Edit the test path in client.py to match a lightweight endpoint from your platform (e.g. /user for GitHub, /v1/me for Spotify). If it prints OK, your connection is good.
OAuth note: For local testing you need a valid access token in
.env. Obtain one from the platform's OAuth playground or developer console. When deployed on Dedalus, DAuth handles the full OAuth flow automatically.
Then start the server and test tools:
python -m src.mainThe server starts on port 8080. Use the client to verify your tools:
python -m src.clientUpdate src/client.py to call your tools by name with the correct arguments.
7. Document Your Project
Update this README with:
What your server does
Available tools and their parameters
Configuration and environment variables
Usage examples
8. Clean Up Template Scaffolding
Once your server is built and working, remove leftover template files so the repo only contains your project code. If you're using an AI coding agent, ask it to perform this cleanup as a final step.
Files to remove:
PROJECT.md— your research notes; no longer needed in the final repoAny remaining
src-*folders (e.g.src-no-auth/,src-api-key/,src-oauth/) that weren't chosencli/,package.json,tsconfig.json— CLI scaffolding tools, not part of your server.env.example— once your.envis set up (optional, some teams keep this for onboarding)
Files to clean up:
src/tools.py— removeExampleResultandexample_tool; only your real tools should remainsrc/client.py— update to call your actual tools with real arguments, or remove if not neededsrc/main.py— remove the placeholder inline comments (e.g.# A short identifier for this connection...) once the values are filled inREADME.md— replace the template guide with project-specific documentation (see step 7)pyproject.toml— update the projectnameanddescriptionto match your server
9. Deploy to Dedalus Labs
Upload your server to dedaluslabs.ai. DAuth handles credential security automatically in production.
Important for OAuth servers: Make sure all OAUTH_* environment variables are configured in the deployment environment. These variables are consumed by the Dedalus platform to handle the OAuth flow — they must be baked into the server at deploy time.
Making Authenticated API Calls with ctx.dispatch()
For API Key and OAuth servers, use ctx.dispatch() to make authenticated requests through DAuth. The framework applies the credential inside the enclave so your code never touches raw secrets.
from dedalus_mcp import tool, get_context, HttpMethod, HttpRequest
from src.main import platform_connection
@tool(description="Fetch user profile")
async def get_profile() -> dict:
ctx = get_context()
req = HttpRequest(method=HttpMethod.GET, path="/user/profile")
resp = await ctx.dispatch(platform_connection, req)
if resp.success and resp.response is not None:
return {"success": True, "data": resp.response.body}
error = resp.error.message if resp.error else "Request failed"
return {"success": False, "error": error}The path is appended to the base_url configured in your Connection object. DAuth attaches the credential to the request using the auth_header_format you specified.
Environment Variables Reference
Variable | Auth Framework | Description |
| API Key, OAuth | Dedalus authorization server URL (default: |
| API Key, OAuth | Your Dedalus platform API key |
| API Key, OAuth | Dedalus API URL (default: |
| API Key | The platform credential (rename to match your platform, e.g. |
| OAuth | Set to |
| OAuth | Platform's OAuth authorization endpoint |
| OAuth | Platform's OAuth token exchange endpoint |
| OAuth | Your OAuth app's client ID |
| OAuth | Your OAuth app's client secret |
| OAuth | Comma-separated list of OAuth scopes |
| OAuth | Platform's API base URL for OAuth requests |
See .env.example for a copy-paste-ready version with sections marked by framework.
Requirements
Python >= 3.10 — for the MCP server
Node.js >= 18 — only needed if using the CLI (
npx create-dmcp)uv (recommended) or pip — for Python dependency management
Links
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseCqualityDmaintenancemcp-starter is a secure, starter framework for building MCP servers with JWT-based authentication, multi-tenant enforcement, and schema validation. Built with Node.js and Docker1561MIT
- Flicense-qualityDmaintenanceA starter template for building MCP servers in Python using the streamable HTTP transport protocol. Provides a foundation with the MCP Python SDK and example configuration to quickly develop custom MCP servers.2
- Alicense-qualityBmaintenanceProduction-ready MCP server starter with authentication, observability, and a plugin system for building and deploying MCP servers quickly.MIT
- Alicense-qualityBmaintenanceA production-ready MCP server template with OAuth 2.1, RBAC, and audit logging for building secure, observable tool servers.MIT
Related MCP Connectors
MCP (Model Context Protocol) server for Appwrite
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
Primarily to be used as a template repository for developing MCP servers with FastMCP in Python, P…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/NickyHeC/granola-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server