Core Contracts - Garume/Manifold GitHub Wiki
The Manifold package is the foundational library upon which the entire Manifold framework is built. It defines the core abstractions — interfaces, descriptor records, enumerations, attributes, and binding primitives — that every other package (Manifold.Cli, Manifold.Mcp, and Manifold.Generators) depends on. This package contains no runtime logic for CLI parsing or MCP transport; it exists purely to establish the contracts that describe operations, their parameters, their execution context, and how results are formatted.
This page provides an exhaustive reference for every public type in the Manifold package. For an understanding of how these contracts are consumed by higher-level packages, see Architecture Overview. For the attributes used to declare operations, see Attributes and Operation Definition. For how the source generator emits code against these contracts, see Source Generator — Manifold.Generators.
The Manifold NuGet package targets .NET 10.0 with the latest C# language version, nullable reference types enabled, and deterministic builds. It has zero external dependencies — every type is self-contained within the Manifold namespace.
Sources: Manifold/Manifold.csproj:1-19, Directory.Build.props:1-16
| Property | Value |
|---|---|
| Package ID | Manifold |
| Target Framework | net10.0 |
| Language Version | latest |
| Nullable | enable |
| External Dependencies | None |
| License | MIT |
The package consists of eight source files defining all public contracts:
| Type | Kind | File | Purpose |
|---|---|---|---|
IOperation<TRequest, TResult> |
Interface | IOperation.cs |
Operation execution contract |
OperationContext |
Sealed class | OperationContext.cs |
Execution context with services |
OperationDescriptor |
Sealed record | DescriptorModels.cs |
Operation metadata |
ParameterDescriptor |
Sealed record | DescriptorModels.cs |
Parameter metadata |
OperationBinding |
Static class | OperationBinding.cs |
Service resolution utility |
IOperationInvoker |
Interface | OperationInvoker.cs |
Reflectionless invocation |
OperationInvocationResult |
Readonly record struct | OperationInvoker.cs |
Invocation result container |
IResultFormatter<TResult> |
Interface | IResultFormatter.cs |
Result-to-text formatting |
InvocationSurface |
Enum | DescriptorModels.cs |
Invocation origin |
OperationVisibility |
Enum | DescriptorModels.cs |
Surface visibility scope |
ParameterSource |
Enum | DescriptorModels.cs |
Parameter binding source |
classDiagram
class IOperation~TRequest TResult~ {
+ExecuteAsync(TRequest, OperationContext) ValueTask~TResult~
}
class OperationContext {
+OperationId : string?
+Surface : InvocationSurface
+Services : IServiceProvider?
+CancellationToken : CancellationToken
+State : object?
+ForCli() OperationContext
+ForMcp() OperationContext
+ForProtocol() OperationContext
+GetService~T~() T?
+GetRequiredService~T~() T
}
class IOperationInvoker {
+TryInvoke(...) bool
}
class OperationInvocationResult {
+Result : object?
+ResultType : Type
+DisplayText : string?
}
class OperationDescriptor {
+OperationId : string
+DeclaringType : Type
+MethodName : string
+ResultType : Type
+Visibility : OperationVisibility
+Parameters : IReadOnlyList~ParameterDescriptor~
}
class ParameterDescriptor {
+Name : string
+ParameterType : Type
+Source : ParameterSource
+Required : bool
}
class IResultFormatter~TResult~ {
+FormatText(TResult, OperationContext) string?
}
class OperationBinding {
+GetRequiredService~T~(IServiceProvider?) T
}
IOperation~TRequest TResult~ --> OperationContext : receives
IOperationInvoker --> OperationInvocationResult : produces
OperationDescriptor --> ParameterDescriptor : contains
OperationDescriptor --> OperationVisibility : uses
ParameterDescriptor --> ParameterSource : uses
OperationContext --> InvocationSurface : uses
IResultFormatter~TResult~ --> OperationContext : receives
Identifies the runtime surface from which an operation was invoked. This enum is threaded through OperationContext and IOperationInvoker, allowing operation implementations to adapt their behavior based on the calling context.
public enum InvocationSurface
{
Unknown = 0,
Cli = 1,
Mcp = 2,
Protocol = 3
}Sources: Manifold/DescriptorModels.cs:3-9
| Value | Integer | Description |
|---|---|---|
Unknown |
0 | Default / unspecified surface |
Cli |
1 | Invoked from a command-line interface |
Mcp |
2 | Invoked via Model Context Protocol |
Protocol |
3 | Direct programmatic invocation |
Controls which invocation surfaces can discover and execute a given operation. The source generator reads this value (derived from [CliOnly] and [McpOnly] attributes) to determine whether to emit CLI commands, MCP tools, or both.
public enum OperationVisibility
{
Both = 0,
CliOnly = 1,
McpOnly = 2
}Sources: Manifold/DescriptorModels.cs:11-16
| Value | Integer | Description |
|---|---|---|
Both |
0 | Visible on both CLI and MCP surfaces |
CliOnly |
1 | Visible only on the CLI surface |
McpOnly |
2 | Visible only on the MCP surface |
Describes where a parameter's value originates during binding. The source generator uses this to emit the correct binding code for each parameter.
public enum ParameterSource
{
Option = 0,
Argument = 1,
Service = 2,
CancellationToken = 3
}Sources: Manifold/DescriptorModels.cs:18-24
| Value | Integer | Description |
|---|---|---|
Option |
0 | Named option (e.g., --name value) |
Argument |
1 | Positional argument |
Service |
2 | Resolved from IServiceProvider
|
CancellationToken |
3 | Injected cancellation token |
For details on how each source is bound at runtime, see Parameter Binding and Type Conversion.
The IOperation<TRequest, TResult> interface is the primary contract for class-based operations. When an operation is defined as a class (as opposed to a static method), it must implement this interface. The source generator detects classes decorated with [Operation] that implement IOperation<,> and emits the appropriate invocation code.
public interface IOperation<in TRequest, TResult>
{
public ValueTask<TResult> ExecuteAsync(TRequest request, OperationContext context);
}Sources: Manifold/IOperation.cs:1-6
Type Parameters:
| Parameter | Variance | Description |
|---|---|---|
TRequest |
Contravariant (in) |
The request/input type carrying parameter values |
TResult |
Invariant | The result type returned after execution |
The TRequest type is typically a record or class with properties matching the operation's parameters. Each property is bound from CLI arguments/options or MCP JSON fields depending on the invocation surface. The TResult type can be any type; it flows through IResultFormatter<TResult> for text conversion and through the surface-specific result types (CliInvocationResult, FastMcpInvocationResult).
flowchart TD
A[Host Application] --> B[IOperationInvoker]
B --> C{Resolve Operation}
C --> D[IOperation.ExecuteAsync]
D --> E[OperationContext]
D --> F[TRequest]
D --> G[ValueTask of TResult]
G --> H[IResultFormatter]
H --> I[Display Text]
OperationContext is a sealed class that carries all ambient information needed during operation execution: the invocation surface, dependency injection services, cancellation support, and optional custom state. Every operation — whether static-method or class-based — receives an OperationContext instance.
Sources: Manifold/OperationContext.cs:1-84
public OperationContext(
string? operationId,
InvocationSurface surface,
IServiceProvider? services = null,
object? state = null,
CancellationToken cancellationToken = default)The constructor normalizes the operationId — if the value is null, empty, or whitespace, it is stored as null; otherwise it is trimmed.
Sources: Manifold/OperationContext.cs:5-17
| Property | Type | Description |
|---|---|---|
OperationId |
string? |
Normalized identifier of the operation being executed |
Surface |
InvocationSurface |
The surface that initiated this invocation |
Services |
IServiceProvider? |
Optional DI container for resolving services |
CancellationToken |
CancellationToken |
Token for cooperative cancellation |
State |
object? |
Arbitrary state passed through by the host |
Three convenience factory methods create OperationContext instances with the Surface pre-set:
public static OperationContext ForCli(
string? operationId = null,
IServiceProvider? services = null,
object? state = null,
CancellationToken cancellationToken = default)
public static OperationContext ForMcp(...)
public static OperationContext ForProtocol(...)Sources: Manifold/OperationContext.cs:29-54
OperationContext provides four methods for resolving services from the Services provider. These methods mirror the Microsoft.Extensions.DependencyInjection patterns but work directly with the IServiceProvider interface without requiring that dependency.
| Method | Return | Behavior |
|---|---|---|
GetService<TService>() |
TService? |
Returns null if not found |
GetService(Type) |
object? |
Returns null if not found |
GetRequiredService<TService>() |
TService |
Throws InvalidOperationException if not found |
GetRequiredService(Type) |
object |
Throws InvalidOperationException if not found |
public TService? GetService<TService>()
where TService : class
{
return Services?.GetService(typeof(TService)) as TService;
}
public object GetRequiredService(Type serviceType)
{
ArgumentNullException.ThrowIfNull(serviceType);
object? service = Services?.GetService(serviceType);
if (service is not null)
return service;
throw new InvalidOperationException(
$"Required service '{serviceType.FullName}' was not available.");
}Sources: Manifold/OperationContext.cs:56-83
For more on how DI integrates with operations, see Dependency Injection and Service Resolution.
The descriptor records provide a metadata model for operations and their parameters. The source generator populates these records at compile time, and they are consumed by the CLI and MCP runtimes to build command structures, generate help text, produce MCP tool catalogs, and perform parameter binding.
flowchart TD
A[Source Generator] --> B[OperationDescriptor]
B --> C[ParameterDescriptor list]
B --> D[CLI Runtime]
B --> E[MCP Runtime]
D --> F[Command Tree]
D --> G[Help Text]
E --> H[Tool Catalog]
E --> I[JSON Schema]
A sealed record that fully describes a single operation — its identity, declaring type, visibility, parameters, and surface-specific overrides.
public sealed record OperationDescriptor(
string OperationId,
Type DeclaringType,
string MethodName,
Type ResultType,
OperationVisibility Visibility,
IReadOnlyList<ParameterDescriptor> Parameters,
string? Description = null,
string? Summary = null,
IReadOnlyList<string>? CliCommandPath = null,
IReadOnlyList<IReadOnlyList<string>>? CliCommandAliases = null,
string? McpToolName = null,
bool Hidden = false,
Type? RequestType = null);Sources: Manifold/DescriptorModels.cs:38-51
| Property | Type | Required | Description |
|---|---|---|---|
OperationId |
string |
Yes | Unique identifier from [Operation] attribute |
DeclaringType |
Type |
Yes | The class or static class that defines the operation |
MethodName |
string |
Yes | Name of the method implementing the operation |
ResultType |
Type |
Yes | The CLR type of the result |
Visibility |
OperationVisibility |
Yes | Which surfaces can see this operation |
Parameters |
IReadOnlyList<ParameterDescriptor> |
Yes | Ordered list of parameter descriptors |
Description |
string? |
No | Detailed description for help/catalog |
Summary |
string? |
No | Brief one-line summary |
CliCommandPath |
IReadOnlyList<string>? |
No | CLI command path segments (e.g., ["file", "copy"]) |
CliCommandAliases |
IReadOnlyList<IReadOnlyList<string>>? |
No | Alternative CLI command paths |
McpToolName |
string? |
No | Override name for MCP tool registration |
Hidden |
bool |
No | If true, operation is hidden from help/catalog |
RequestType |
Type? |
No | Request class type for class-based operations |
A sealed record that describes a single parameter of an operation, including its binding source and surface-specific name overrides.
public sealed record ParameterDescriptor(
string Name,
Type ParameterType,
ParameterSource Source,
bool Required,
int? Position = null,
string? Description = null,
IReadOnlyList<string>? Aliases = null,
string? CliName = null,
string? McpName = null,
string? RequestPropertyName = null);Sources: Manifold/DescriptorModels.cs:26-36
| Property | Type | Required | Description |
|---|---|---|---|
Name |
string |
Yes | Canonical parameter name |
ParameterType |
Type |
Yes | CLR type of the parameter |
Source |
ParameterSource |
Yes | Where the value comes from (Option, Argument, Service, CancellationToken) |
Required |
bool |
Yes | Whether the parameter must be provided |
Position |
int? |
No | Positional index for Argument source |
Description |
string? |
No | Help text for this parameter |
Aliases |
IReadOnlyList<string>? |
No | Alternative names (e.g., -n for --name) |
CliName |
string? |
No | Override name on the CLI surface |
McpName |
string? |
No | Override name on the MCP surface |
RequestPropertyName |
string? |
No | Property name in the request type for class-based operations |
A static utility class used by generated code to resolve required services from an IServiceProvider. This is called during parameter binding when a parameter is marked with [FromServices].
public static class OperationBinding
{
public static TService GetRequiredService<TService>(IServiceProvider? services)
where TService : class
{
object? service = services?.GetService(typeof(TService));
if (service is TService typedService)
return typedService;
throw new InvalidOperationException(
$"Required service '{typeof(TService).FullName}' was not available.");
}
}Sources: Manifold/OperationBinding.cs:1-14
The generated invoker code calls OperationBinding.GetRequiredService<T>(services) for each [FromServices] parameter. This keeps the generated code simple — a single static call — while providing a clear error message when a service is missing.
A readonly record struct that wraps the result of an operation invocation along with type information and optional pre-formatted display text.
public readonly record struct OperationInvocationResult(
object? Result,
Type ResultType,
string? DisplayText = null);Sources: Manifold/OperationInvoker.cs:3-6
| Property | Type | Description |
|---|---|---|
Result |
object? |
The boxed result value |
ResultType |
Type |
The CLR type of the result |
DisplayText |
string? |
Pre-formatted text from IResultFormatter
|
The IOperationInvoker interface defines the surface-agnostic contract for invoking operations by their string identifier. The source generator emits a GeneratedCliInvoker and related types that implement this interface.
public interface IOperationInvoker
{
public bool TryInvoke(
string operationId,
object? request,
IServiceProvider? services,
InvocationSurface surface,
CancellationToken cancellationToken,
out ValueTask<OperationInvocationResult> invocation);
}Sources: Manifold/OperationInvoker.cs:8-17
The TryInvoke method follows the Try pattern: it returns true if the operation was found and invocation began, writing the asynchronous result to the out parameter; it returns false if the operationId is not recognized.
flowchart TD
A[Caller provides operationId] --> B[IOperationInvoker.TryInvoke]
B --> C{Operation Found?}
C -- Yes --> D[Bind Parameters]
D --> E[Execute Operation]
E --> F[OperationInvocationResult]
C -- No --> G[Return false]
The IResultFormatter<TResult> interface allows operations to define custom text formatting for their results. When an operation is decorated with [ResultFormatter(typeof(MyFormatter))], the generated invoker calls the formatter after execution to produce display text.
public interface IResultFormatter<in TResult>
{
public string? FormatText(TResult result, OperationContext context);
}Sources: Manifold/IResultFormatter.cs:1-6
The FormatText method receives both the result and the OperationContext, enabling surface-aware formatting. Returning null indicates that no special formatting is needed and the default behavior should apply.
For details on result types and formatting across surfaces, see Result Types and Formatting.
The Manifold package defines all attributes used to annotate operations and their parameters. These attributes are read at compile time by the source generator, not at runtime via reflection.
The primary attribute for declaring an operation. Can be applied to both static methods and classes.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
AllowMultiple = false, Inherited = false)]
public class OperationAttribute(string operationId) : Attribute
{
public string OperationId { get; }
public string? Description { get; set; }
public string? Summary { get; set; }
public bool Hidden { get; set; }
}Sources: Manifold/OperationAttribute.cs:1-15
The operationId constructor parameter is validated to be non-empty and is trimmed. Description and Summary are optional metadata used for help text and MCP tool catalogs.
Overrides the default CLI command path for an operation.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class CliCommandAttribute(params string[] pathSegments) : Attribute
{
public string[] PathSegments { get; }
}Sources: Manifold/ParameterAttributes.cs:66-75
Path segments are filtered for empty values and trimmed. At least one segment is required.
Overrides the default MCP tool name for an operation.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class McpToolAttribute(string name) : Attribute
{
public string Name { get; }
}Sources: Manifold/ParameterAttributes.cs:77-83
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class CliOnlyAttribute : Attribute;
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class McpOnlyAttribute : Attribute;Sources: Manifold/ParameterAttributes.cs:85-89
These marker attributes set OperationVisibility.CliOnly or OperationVisibility.McpOnly respectively. Applying both to the same operation produces diagnostic DMCF001 at compile time. See Diagnostics and Compile-Time Validation.
Associates an IResultFormatter<TResult> implementation with an operation.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class ResultFormatterAttribute(Type formatterType) : Attribute
{
public Type FormatterType { get; }
}Sources: Manifold/ParameterAttributes.cs:94-98
Marks a parameter as a named option (e.g., --name value on CLI, "name": "value" in MCP JSON).
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
public class OptionAttribute(string name) : Attribute
{
public string Name { get; }
public string? Description { get; set; }
public bool Required { get; set; } = true;
}Sources: Manifold/ParameterAttributes.cs:3-13
Marks a parameter as a positional argument. The position must be zero or greater.
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
public sealed class ArgumentAttribute(int position) : Attribute
{
public int Position { get; }
public string? Name { get; set; }
public string? Description { get; set; }
public bool Required { get; set; } = true;
}Sources: Manifold/ParameterAttributes.cs:15-27
Applying both [Option] and [Argument] to the same parameter produces diagnostic DMCF002.
Provides alternative names for commands or parameters. Supports multiple applications (AllowMultiple = true).
[AttributeUsage(... AllowMultiple = true)]
public sealed class AliasAttribute(params string[] aliases) : Attribute
{
public string[] Aliases { get; }
}Sources: Manifold/ParameterAttributes.cs:29-48
Aliases are normalized: empty values are removed, remaining values are trimmed, and duplicates (case-insensitive) are eliminated. At least one valid alias is required.
Override the parameter name on a specific surface without affecting the other.
public sealed class CliNameAttribute(string name) : Attribute { ... }
public sealed class McpNameAttribute(string name) : Attribute { ... }Sources: Manifold/ParameterAttributes.cs:50-64
Marks a parameter for dependency injection. Parameters with this attribute have ParameterSource.Service and are resolved from IServiceProvider at invocation time.
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class FromServicesAttribute : Attribute;Sources: Manifold/ParameterAttributes.cs:91-92
For full details on all attributes, see Attributes and Operation Definition.
| Attribute | Targets | AllowMultiple | Purpose |
|---|---|---|---|
[Operation] |
Method, Class | No | Declares an operation |
[CliCommand] |
Method, Class | No | Custom CLI command path |
[McpTool] |
Method, Class | No | Custom MCP tool name |
[CliOnly] |
Method, Class | No | Restrict to CLI surface |
[McpOnly] |
Method, Class | No | Restrict to MCP surface |
[ResultFormatter] |
Method, Class | No | Custom result formatter |
[Option] |
Parameter, Property | No | Named option binding |
[Argument] |
Parameter, Property | No | Positional argument binding |
[Alias] |
Method, Class, Parameter, Property | Yes | Alternative names |
[CliName] |
Method, Class, Parameter, Property | No | CLI name override |
[McpName] |
Method, Class, Parameter, Property | No | MCP name override |
[FromServices] |
Parameter | No | DI service injection |
The following diagram shows how core contracts are used across the full operation lifecycle — from definition through generation to invocation.
sequenceDiagram
participant Dev as Developer
participant Gen as Source Generator
participant Reg as OperationDescriptor Registry
participant Host as Host Application
participant Inv as IOperationInvoker
participant Op as IOperation / Static Method
participant Ctx as OperationContext
participant Fmt as IResultFormatter
Dev->>Gen: Annotate with [Operation]
Gen->>Reg: Emit OperationDescriptor records
Gen->>Inv: Emit generated invoker
Host->>Inv: TryInvoke(operationId, request, ...)
Inv->>Ctx: Create OperationContext
Inv->>Op: ExecuteAsync(request, context)
Op->>Ctx: GetService / GetRequiredService
Op-->>Inv: ValueTask of TResult
Inv->>Fmt: FormatText(result, context)
Fmt-->>Inv: Display text
Inv-->>Host: OperationInvocationResult
The Manifold package deliberately has no NuGet dependencies. It uses only BCL types (IServiceProvider, Type, CancellationToken, ValueTask<T>). This ensures that the contracts can be referenced by any .NET project without introducing transitive dependencies.
Both OperationDescriptor and ParameterDescriptor are sealed records, providing value equality, immutability, and with-expression support. This allows the source generator to emit compact construction code and enables runtime systems to safely cache and compare descriptors.
OperationInvocationResult is a readonly record struct, avoiding heap allocation for the common case where the result flows synchronously through the invocation pipeline. This aligns with the zero-allocation fast-path design documented in Performance and Benchmarks.
The InvocationSurface enum and OperationVisibility enum work together to provide a clean separation between the CLI and MCP surfaces. Operations can be written once and exposed on both surfaces, or restricted to one, without any changes to the operation logic itself.
- Architecture Overview — How the four packages relate to each other
- Attributes and Operation Definition — Full reference for all attributes
- Source Generator — Manifold.Generators — How descriptors and invokers are generated
- CLI Runtime — Manifold.Cli — How CLI uses these contracts
- MCP Runtime — Manifold.Mcp — How MCP uses these contracts
- Parameter Binding and Type Conversion — How parameter sources are resolved
- Dependency Injection and Service Resolution — Service resolution via OperationContext
- Result Types and Formatting — IResultFormatter and result handling
- Diagnostics and Compile-Time Validation — Compile-time validation of attribute usage
- Performance and Benchmarks — Zero-allocation design details
- Sample Operations Reference — Practical usage examples