Initial public release
Build Docker Image / build (push) Failing after 1m22s

MCP (Model Context Protocol) server for reading and writing an Obsidian
vault, gated by OAuth-issued JWT bearer tokens. See README.md for setup.
This commit is contained in:
2026-05-17 23:53:00 +08:00
commit 515763bc72
31 changed files with 1931 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
namespace ObsidianMcp.Config;
/// <summary>
/// JWT 验签配置。
/// 环境变量:Jwt__Issuer, Jwt__Audience, Jwt__SigningKey__Current, Jwt__SigningKey__Previous
/// </summary>
public class JwtOptions
{
public const string Section = "Jwt";
/// <summary>期望的 iss claim(你的 auth server 的 issuer URL),必须通过 env 注入</summary>
public string Issuer { get; set; } = string.Empty;
/// <summary>期望的 aud claim,默认 obsidian</summary>
public string Audience { get; set; } = "obsidian";
public SigningKeyPair SigningKey { get; set; } = new();
public class SigningKeyPair
{
/// <summary>当前签名密钥(HS256 对称密钥),env: Jwt__SigningKey__Current</summary>
public string Current { get; set; } = string.Empty;
/// <summary>上一轮密钥,密钥轮换过渡期用,env: Jwt__SigningKey__Previous(可为空)</summary>
public string? Previous { get; set; }
}
}
+22
View File
@@ -0,0 +1,22 @@
namespace ObsidianMcp.Config;
/// <summary>
/// /.well-known/oauth-authorization-server + /.well-known/oauth-protected-resource
/// 端点返回的元数据。环境变量前缀 Mcp__OAuthDiscovery__。
/// </summary>
public class McpDiscoveryOptions
{
public const string Section = "Mcp:OAuthDiscovery";
public string Issuer { get; set; } = string.Empty;
public string AuthorizationEndpoint { get; set; } = string.Empty;
public string TokenEndpoint { get; set; } = string.Empty;
public string RegistrationEndpoint { get; set; } = string.Empty;
/// <summary>
/// 本资源服务的标识符(RFC 9728 PRM 的 `resource` 字段,必须与 auth server
/// 上该资源条目的 resource_url 完全一致)。
/// 留空时 PRM 端点回退用请求的 `scheme://host`。
/// </summary>
public string ResourceUrl { get; set; } = string.Empty;
}
+19
View File
@@ -0,0 +1,19 @@
namespace ObsidianMcp.Config;
/// <summary>
/// Vault 根目录与路径安全配置。
/// 环境变量前缀 Vault__,例如 Vault__Root=/vault
/// </summary>
public class VaultOptions
{
public const string Section = "Vault";
/// <summary>Vault 根目录的绝对路径,容器内默认 /vault</summary>
public string Root { get; set; } = "/vault";
/// <summary>额外黑名单路径段(与 hardcode 合并),env: Vault__Blacklist__0, __1...</summary>
public string[] Blacklist { get; set; } = [];
/// <summary>额外写入白名单前缀(与 hardcode 合并),env: Vault__WriteWhitelist__0...</summary>
public string[] WriteWhitelist { get; set; } = [];
}