Skip to content
Tracon

McpServerDefinition

Namespace Tracon · Assembly Tracon.Abstractions.dll

A registered remote MCP server. Its tools are discovered at connection time and listed alongside the tools registered in code.

public sealed record McpServerDefinition : IEquatable<McpServerDefinition>
Inheritance
object ← McpServerDefinition
Implements
IEquatable<McpServerDefinition>
Inherited Members
object.GetType(), object.ToString(), object.Equals(object?), object.Equals(object?, object?), object.ReferenceEquals(object?, object?), object.GetHashCode()

Carries no secret. The value of a credential header is not stored in this record; only the name of the configuration key the value is read from (HeaderConfigurationKeys) is stored. The value is resolved at connection time through IConfiguration, so it stays in dotnet user-secrets or an environment variable. It never enters a database backup, an audit trail, or a UI response.

public McpServerDefinition()

The creation time (UTC).

public DateTimeOffset CreatedAt { get; init; }

DateTimeOffset

The description.

public string? Description { get; init; }

string?

Whether the server is enabled. Its tools are not discovered while disabled.

public bool Enabled { get; init; }

bool

The server address. Only http and https are accepted.

public required Uri Endpoint { get; init; }

Uri

Credential request headers, as a map from the header name to the NAME of the configuration key its value is read from. The value is resolved through IConfiguration on every connection and is never stored.

public IReadOnlyDictionary<string, string> HeaderConfigurationKeys { get; init; }

IReadOnlyDictionary<string, string>

var record = new McpServerDefinition
{
Id = Guid.NewGuid(),
TenantId = "acme",
Name = "search",
Endpoint = new Uri("https://mcp.example.com/mcp"),
HeaderConfigurationKeys = new Dictionary<string, string>
{
["X-Api-Key"] = "Tracon:McpSecrets:acme:SearchKey",
},
};

Every key name must sit under TraconMcpSecurityOptions.AllowedConfigurationPrefix, inside the tenant’s own key space ({prefix}{tenantId}:...; a flat name directly under the prefix belongs to the default tenant). The rule is checked on save and again on every connection.

A header name may appear only once across McpServerDefinition.Headers and this map, compared case-insensitively. While OAuth is on, the map may not name Authorization.

Extra request headers, sent as given with every request to the server. An HTTP response never returns a stored value: it carries every header name with the value ***.

public IReadOnlyDictionary<string, string> Headers { get; init; }

IReadOnlyDictionary<string, string>

The values are stored as plain text in the database. Do not put a secret here: declare a credential header in HeaderConfigurationKeys instead. The HTTP save rejects a header whose name looks like a credential (Authorization, X-Api-Key, Cookie, any name ending in -key).

The list and save responses mask every value, and the audit trail records the names only. A save whose header value is *** is rejected, so a client that reads, edits and saves a server must send every header value again.

The server identifier. A time-ordered UUID (v7).

public required Guid Id { get; init; }

Guid

The server name. Discovered tools are named as {name}.{tool}, so tools with the same name on two servers never collide.

public required string Name { get; init; }

string

The OAuth authorization flow.

[JsonPropertyName("oauthAuthorizationMode")]
public McpOAuthAuthorizationMode OAuthAuthorizationMode { get; init; }

McpOAuthAuthorizationMode

The OAuth client identifier. Not a secret, stored as-is.

[JsonPropertyName("oauthClientId")]
public string? OAuthClientId { get; init; }

string?

The configuration key the OAuth client secret’s value is read from. The value is never written to the database, under the same rule as HeaderConfigurationKeys.

[JsonPropertyName("oauthClientSecretConfigurationKey")]
public string? OAuthClientSecretConfigurationKey { get; init; }

string?

Whether OAuth authentication is on. When on, HeaderConfigurationKeys may not name Authorization — both would try to manage that header.

[JsonPropertyName("oauthEnabled")]
public bool OAuthEnabled { get; init; }

bool

[JsonPropertyName] is given deliberately: System.Text.Json’s camelCase policy lowercases only the first letter, and since “OAuth” starts with two uppercase letters, the default output would be oAuthEnabled (not the expected oauthEnabled). The same constraint applies to all four OAuth fields below.

The space-separated OAuth scope list. Example: "repo read:user".

[JsonPropertyName("oauthScopes")]
public string? OAuthScopes { get; init; }

string?

Whether this server’s tools require explicit approval before each call. Defaults to true: the tool definition comes from outside and is treated as untrusted.

public bool RequiresApproval { get; init; }

bool

The tenant the server belongs to.

public required string TenantId { get; init; }

string

The transport format.

public McpTransportMode Transport { get; init; }

McpTransportMode

The last-updated time (UTC).

public DateTimeOffset UpdatedAt { get; init; }

DateTimeOffset

public override bool Equals(object? obj)

obj object?

bool

public bool Equals(McpServerDefinition? other)

other McpServerDefinition?

bool

public override int GetHashCode()

int

public override string ToString()

string

operator ==(McpServerDefinition?, McpServerDefinition?)

Section titled “ operator ==(McpServerDefinition?, McpServerDefinition?)”
public static bool operator ==(McpServerDefinition? left, McpServerDefinition? right)

left McpServerDefinition?

right McpServerDefinition?

bool

operator !=(McpServerDefinition?, McpServerDefinition?)

Section titled “ operator !=(McpServerDefinition?, McpServerDefinition?)”
public static bool operator !=(McpServerDefinition? left, McpServerDefinition? right)

left McpServerDefinition?

right McpServerDefinition?

bool