Files
obsidian-mcp/Program.cs
T
zhengchen.tao 515763bc72
Build Docker Image / build (push) Failing after 1m22s
Initial public release
MCP (Model Context Protocol) server for reading and writing an Obsidian
vault, gated by OAuth-issued JWT bearer tokens. See README.md for setup.
2026-05-17 23:55:00 +08:00

84 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.AspNetCore.Authorization;
using ObsidianMcp.Auth;
using ObsidianMcp.Config;
using ObsidianMcp.Endpoints;
using ObsidianMcp.Services;
var builder = WebApplication.CreateBuilder(args);
// ─── 配置绑定 ───────────────────────────────────────────────────────────────
var jwtOpts = builder.Configuration.GetSection(JwtOptions.Section).Get<JwtOptions>()
?? new JwtOptions();
// ─── 配置对象注册到 DI ───────────────────────────────────────────────────────
builder.Services.Configure<VaultOptions>(
builder.Configuration.GetSection(VaultOptions.Section));
builder.Services.Configure<JwtOptions>(
builder.Configuration.GetSection(JwtOptions.Section));
// McpDiscoveryOptions 直接注册为单例(供 DiscoveryEndpoints 依赖注入)
var discoveryOpts = builder.Configuration.GetSection(McpDiscoveryOptions.Section).Get<McpDiscoveryOptions>()
?? new McpDiscoveryOptions();
builder.Services.AddSingleton(discoveryOpts);
// ─── 认证与授权 ──────────────────────────────────────────────────────────────
builder.Services.AddObsidianJwtBearer(jwtOpts);
builder.Services.AddAuthorization(opts =>
{
opts.AddScopePolicies();
// 默认 policy:只要求已认证(JWT 验签通过即可),不要求特定 scope
opts.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
// scope 自定义 handler
builder.Services.AddSingleton<IAuthorizationHandler, ScopeAuthorizationHandler>();
// IHttpContextAccessorTool 里取 User / scope 用)
builder.Services.AddHttpContextAccessor();
// ─── MCP SDK ─────────────────────────────────────────────────────────────────
builder.Services.AddMcpServer()
.WithHttpTransport() // Streamable HTTP(单端点 POST /mcp
.WithToolsFromAssembly(); // 自动扫描 [McpServerToolType]
// ─── 业务服务 ────────────────────────────────────────────────────────────────
builder.Services.AddSingleton<VaultPathResolver>();
builder.Services.AddSingleton<VaultWriteGuard>();
builder.Services.AddSingleton<VaultSearchService>();
builder.Services.AddSingleton<AuditLogger>();
// ─── Build ───────────────────────────────────────────────────────────────────
var app = builder.Build();
// ─── Middleware 顺序(顺序不能乱)───────────────────────────────────────────
app.UseAuthentication();
app.UseAuthorization();
// ─── 路由 ────────────────────────────────────────────────────────────────────
// /.well-known/oauth-authorization-server(不需要认证)
app.MapDiscoveryEndpoints();
// 健康检查(方便 docker compose 和 NPM 探活)
app.MapGet("/health", () => Results.Ok(new { status = "ok", time = DateTime.UtcNow }))
.AllowAnonymous();
// MCP 端点(必须认证,Bearer JWT)。
// 端点级只校验"已认证"scope 校验放在每个 Tool 里:
// - 读 tool 校验 read:obsidian
// - 写 tool 校验 write:obsidian
// 这样客户端拿单一 scope(仅读 / 仅写)的 Token 都能正常用对应工具。
app.MapMcp("/mcp").RequireAuthorization();
app.Run();