MCP tools are often described as functions that an AI model can call.
From a production engineering perspective, that description is incomplete.
An MCP tool is also an API contract.
Consider:
Tool Name
↓
Input Schema
↓
Validation
↓
Authorization
↓
Execution
↓
Result ContractIf any part of that contract changes unexpectedly, an MCP client or AI agent can fail even when the C# code still compiles.
This is why unit testing the method itself is not enough.
A production MCP server should test the contract exposed over MCP, including:
Tool discovery
Tool names
Input schemas
Valid parameters
Invalid parameters
Error behavior
Result structure
Protocol compatibility
Header consistency
Stateless behavior
Regression cases
The official MCP Conformance Test Framework exists specifically to test MCP client and server implementations against the specification. It can capture protocol interactions, validate behavior, and perform wire-schema checks.
For application teams, however, conformance testing should complement—not replace—application-specific contract tests.
What Is an MCP Tool Contract?
Suppose an MCP server exposes:
[McpServerTool(Name = "get_order_status")]
public static async Task<string> GetOrderStatus(
string orderId)
{
// Implementation
}The contract is larger than this C# method.
Conceptually:
get_order_status
|
+-- Required parameter: orderId
|
+-- Parameter type: string
|
+-- Valid values
|
+-- Authorization requirements
|
+-- Success result
|
+-- Failure behavior
|
+-- Protocol representationA developer might change:
string orderIdto:
int orderIdand still have a perfectly valid C# application.
But an existing MCP client may have been built around the original schema.
That is a contract change.
Why Unit Tests Are Not Enough
Consider a unit test:
[Fact]
public async Task GetOrderStatus_ReturnsOrder()
{
var result =
await OrderService.GetStatusAsync("ORD-100");
Assert.NotNull(result);
}This verifies business logic.
It does not verify:
MCP tool name
MCP schema
JSON serialization
Tool discovery
HTTP transport
Protocol negotiation
Authorization
Error mappingA stronger testing strategy has multiple layers:
Unit Tests
↓
Tool Contract Tests
↓
MCP Integration Tests
↓
Conformance Tests
↓
End-to-End TestsEach layer answers a different question.
Unit Tests vs Contract Tests
| Test Type | Main Question |
|---|---|
| Unit | Does the business method work? |
| Contract | Does the tool expose the expected interface? |
| Integration | Does MCP communication work end to end? |
| Conformance | Does the implementation follow the MCP specification? |
| E2E | Does the complete agent workflow work? |
A mature MCP application should not depend on one of these layers alone.
Start With a Contract Definition
Before writing tests, define the expected contract.
For example:
Tool:
get_order_status
Required:
orderId
Type:
string
Authorization:
orders.read
Success:
Order status
Invalid:
Validation error
Unknown order:
Not foundYou can represent the expected contract in a test fixture:
public sealed record ToolContract(
string Name,
string RequiredParameter,
string RequiredScope);Then:
var contract = new ToolContract(
"get_order_status",
"orderId",
"orders.read");The exact representation is application-specific.
The important part is that the expected contract is explicit.
Test Tool Discovery
An MCP client should be able to discover the tool.
Using the C# SDK, a client can list tools through ListToolsAsync. The official SDK also provides an in-memory transport that is specifically useful for testing servers without requiring network overhead.
A simplified test can look like:
[Fact]
public async Task Server_Exposes_GetOrderStatus()
{
await using var client = CreateTestClient();
var tools =
await client.ListToolsAsync();
var tool =
tools.FirstOrDefault(
x => x.Name == "get_order_status");
Assert.NotNull(tool);
}This catches a surprisingly common class of regression:
Expected:
get_order_status
Actual:
getOrderStatusThe implementation may still compile, but the MCP contract changed.
Test the Input Schema
Tool discovery should also verify the schema.
For example:
orderId
required = true
type = stringThe exact schema representation exposed by the SDK can evolve with the protocol, so tests should assert the contract properties that your application actually depends on rather than comparing an entire serialized schema string unnecessarily.
For example:
Assert.Contains(
tool.InputSchema.Required,
"orderId");The exact API surface should match the SDK version used by your project.
Avoid Brittle Schema Tests
This is too strict:
Assert.Equal(
expectedEntireJson,
actualSchemaJson);A harmless schema serialization change could break the test.
Prefer targeted assertions:
Tool name
Required fields
Field types
Important constraintsUse full snapshots only when the serialized representation itself is a contractual requirement.
Test Required Parameters
A required parameter should remain required.
For example:
Valid:
orderId = "ORD-100"
Invalid:
orderId = nullThe test should verify that the invalid call does not reach business execution.
Conceptually:
[Fact]
public async Task Missing_OrderId_Is_Rejected()
{
await using var client = CreateTestClient();
var tool =
await GetToolAsync(
client,
"get_order_status");
await Assert.ThrowsAsync<Exception>(
() => tool.InvokeAsync(
new Dictionary<string, object?>()));
}The exact exception type depends on how the SDK surfaces protocol and validation failures.
The important assertion is that invalid input is rejected at the appropriate layer.
Test Valid Input
A valid request should reach the expected business operation.
[Fact]
public async Task Valid_OrderId_Returns_Result()
{
await using var client = CreateTestClient();
var tool =
await GetToolAsync(
client,
"get_order_status");
var result =
await tool.InvokeAsync(
new Dictionary<string, object?>
{
["orderId"] = "ORD-100"
});
Assert.NotNull(result);
}The test should verify both:
Protocol success
+
Business resultTest Invalid Input Explicitly
Do not test only missing values.
Test:
Empty string
Malformed ID
Too long
Unsupported format
Unknown resource
Invalid enum
Unexpected valueFor example:
[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData("INVALID")]
public async Task Invalid_OrderId_Is_Rejected(
string orderId)
{
await using var client = CreateTestClient();
var tool =
await GetToolAsync(
client,
"get_order_status");
await Assert.ThrowsAsync<Exception>(
() => tool.InvokeAsync(
new Dictionary<string, object?>
{
["orderId"] = orderId
}));
}The specific validation rules should come from the application's real contract.
Do not invent validation requirements merely to increase test coverage.
Test Unknown Parameters
An MCP tool contract should define how unexpected parameters are handled.
For example:
{
"orderId": "ORD-100",
"unexpected": "value"
}Depending on the schema and server behavior, this may be rejected or ignored.
Your test should document the behavior your application requires.
This prevents accidental changes during SDK upgrades.
Test Result Contracts
Input validation is only half the contract.
Suppose the tool currently returns:
{
"orderId": "ORD-100",
"status": "Shipped"
}A future change could return:
{
"id": "ORD-100",
"state": "Shipped"
}The C# method might still work.
A dependent client could fail.
Create result-level contract tests for fields that clients actually consume.
For example:
Assert.Equal(
"ORD-100",
result.OrderId);
Assert.Equal(
"Shipped",
result.Status);Test Error Contracts
Errors are part of the API contract.
Test distinct failure conditions:
Validation failure
Authentication failure
Authorization failure
Not found
Dependency failure
Timeout
Cancellation
Unexpected exceptionDo not simply assert:
Any exception = passThat hides meaningful regressions.
A better test verifies the expected category:
Invalid input
↓
Validation failure
Missing permission
↓
Authorization failure
Unknown order
↓
Not foundTest Authorization Separately
Consider:
get_order_statuswith:
Required scope:
orders.readCreate tests for:
Valid scope
Missing scope
Wrong scope
Wrong tenant
Unauthenticated requestFor example:
[Fact]
public async Task Missing_Order_Read_Scope_Is_Denied()
{
// Arrange a client with insufficient permissions.
// Invoke the MCP tool.
// Assert that authorization fails.
}The implementation depends on your authentication setup.
The contract should not.
Test Tenant Isolation
Multi-tenant MCP servers require an additional contract.
Suppose:
Tenant A:
ORD-100
Tenant B:
ORD-200A user authenticated against Tenant A must not retrieve Tenant B's order.
Test this explicitly:
Authenticated tenant = A
Requested order = B
Expected = deniedThis should be an integration/security test, not merely a unit test.
Parameter values and MCP headers should never be treated as proof of tenant authorization.
Test Tool Names as Stable Contracts
Tool names are often consumed directly by clients and AI agents.
Changing:
get_order_statusto:
fetch_order_statusmay appear harmless.
It is not necessarily backward compatible.
A contract test should fail if an established tool disappears unexpectedly:
Assert.Contains(
tools,
tool => tool.Name == "get_order_status");If a rename is intentional, treat it as a versioned contract change.
Test Tool Removal Deliberately
The opposite case matters too.
If a deprecated tool is intentionally removed:
old_toolthen the test suite should explicitly change.
This prevents a developer from accidentally restoring obsolete behavior simply to satisfy old tests.
Tests should protect intended contracts, not freeze every historical behavior forever.
Test MCP Protocol Metadata
MCP 2.0 introduces standardized HTTP metadata, including:
Mcp-Method
Mcp-Name
Mcp-Param-*These headers can be used by infrastructure to inspect MCP requests without parsing the JSON-RPC body. The official SDK documents this as part of the 2026-07-28 protocol revision.
Contract tests should verify important metadata behavior where your deployment depends on it.
For example:
Mcp-Name:
get_order_status
JSON-RPC tool:
get_order_statusThese values should not silently diverge.
Test Header/Body Mismatches
This is an important negative test.
Send:
Mcp-Name: get_order_statuswhile the JSON-RPC request asks for:
delete_orderThe MCP 2.0 protocol treats the JSON-RPC body as authoritative and rejects inconsistent standardized headers.
Your integration test should verify that behavior.
Conceptually:
[Fact]
public async Task Mismatched_Tool_Header_Is_Rejected()
{
// Build request with conflicting MCP metadata.
// Send request.
// Assert protocol rejection.
}This protects against infrastructure/application disagreement.
Test Stateless HTTP
MCP C# SDK 2.0 uses stateless HTTP by default.
The SDK documentation states that stateless HTTP does not create an Mcp-Session-Id or track transport session state in memory, which makes horizontal scaling easier.
Your integration tests should therefore avoid accidentally depending on a single server process.
A useful test architecture is:
Test Client
↓
HTTP Endpoint
↓
MCP ServerThen repeat requests independently.
Test Requests Across Instances
For production-like validation:
Request 1 → Server A
Request 2 → Server BThe operation should work when the application does not require transport session affinity.
If it fails because Server B does not know something that Server A stored in memory, you have discovered hidden state.
This test is particularly important after migrating from an older stateful configuration.
Use In-Memory Transport for Fast Tests
The C# SDK provides StreamServerTransport and StreamClientTransport for connecting a server and client through streams. The official documentation specifically identifies in-memory transport as useful for testing and embedding a client and server in the same process.
A simplified setup is:
var clientToServer = new Pipe();
var serverToClient = new Pipe();
await using var server =
McpServer.Create(
new StreamServerTransport(
clientToServer.Reader.AsStream(),
serverToClient.Writer.AsStream()),
options);
_ = server.RunAsync();
await using var client =
await McpClient.CreateAsync(
new StreamClientTransport(
clientToServer.Writer.AsStream(),
serverToClient.Reader.AsStream()));This is useful when you want fast protocol-level tests without starting a real HTTP server.
When to Use In-Memory Versus HTTP
| Scenario | Recommended Test |
|---|---|
| Tool logic | Unit test |
| Tool discovery | In-memory integration |
| Schema | In-memory integration |
| Basic MCP invocation | In-memory integration |
| HTTP headers | HTTP integration |
| Gateway behavior | HTTP/infrastructure test |
| Load balancing | Multi-instance integration |
| OAuth | HTTP integration |
| Full protocol compliance | Conformance suite |
| End-user workflow | End-to-end test |
This layered approach keeps the test suite fast without sacrificing coverage.
Build a Test Server Fixture
Avoid rebuilding the entire MCP server setup in every test.
Create a reusable fixture:
public sealed class McpServerFixture
: IAsyncLifetime
{
public McpClient Client { get; private set; } = default!;
public async Task InitializeAsync()
{
Client =
await CreateTestClientAsync();
}
public async Task DisposeAsync()
{
await Client.DisposeAsync();
}
}Then:
public class ToolContractTests
: IClassFixture<McpServerFixture>
{
private readonly McpServerFixture _fixture;
public ToolContractTests(
McpServerFixture fixture)
{
_fixture = fixture;
}
[Fact]
public async Task Tool_Is_Exposed()
{
var tools =
await _fixture.Client.ListToolsAsync();
Assert.Contains(
tools,
x => x.Name == "get_order_status");
}
}The exact lifetime strategy should match your test framework and whether the MCP client/server objects are safe to share.
Keep Test Data Deterministic
Avoid tests that depend on production-like random data.
Prefer:
ORD-100
ORD-200
TENANT-A
TENANT-Binside a controlled test environment.
For example:
public static class TestData
{
public const string OrderId =
"ORD-100";
public const string TenantA =
"TENANT-A";
}Deterministic fixtures make failures reproducible.
Test Negative Cases First-Class
A weak MCP test suite might contain:
100 successful calls
0 invalid callsThat does not provide strong contract protection.
A better suite covers:
Valid
Invalid
Unauthorized
Malformed
Missing
Conflicting
Expired
Cancelled
RepeatedThe exact categories depend on the tool.
Add Contract Tests for Every Important Tool
For a server containing:
search_products
get_order_status
create_order
cancel_ordermaintain a contract suite:
search_products
├── discovery
├── schema
├── valid input
├── invalid input
└── errors
get_order_status
├── discovery
├── schema
├── authorization
└── result
create_order
├── schema
├── authorization
├── idempotency
└── validationNot every tool needs exactly the same tests.
Sensitive or side-effecting tools generally need more coverage.
Test Side-Effecting Tools Carefully
Consider:
create_orderA test should not accidentally create duplicate records.
Use a test database or mocked dependency with controlled behavior.
For idempotency:
Call 1
↓
Order created
Call 2 with same operation ID
↓
Existing result returnedThe expected behavior should be explicitly documented.
Test Cancellation
MCP tools can perform network and database operations.
Cancellation should propagate where possible.
For example:
[Fact]
public async Task Tool_Respects_Cancellation()
{
using var cts =
new CancellationTokenSource();
cts.Cancel();
// Invoke tool with the cancelled token.
// Verify the operation stops
// according to the application's contract.
}The exact behavior depends on the tool implementation.
The test should ensure that cancellation does not accidentally turn into an unrelated successful side effect.
Test Timeouts
If a tool calls an external dependency, simulate:
Dependency delay
Dependency timeout
Dependency unavailableThen verify that the MCP server exposes a controlled failure.
Do not let a test simply wait until the test runner times out.
A production timeout should be explicit and observable.
Test Multi-Round Requests
MCP 2.0 introduces Multi Round-Trip Requests for interactive tools.
A tool can return an input-required result containing input requests and opaque request state. The client then sends the collected input and request state back in a later request.
Test the complete sequence:
Round 1
↓
Input required
Round 2
↓
Input supplied
Final resultThen test:
Missing input
Invalid input
Expired state
Wrong state
Retry
CancellationThis should be treated as a workflow contract rather than a single method call.
Test Different Server Instances for MRTR
If the server is stateless:
Round 1 → Instance A
Round 2 → Instance Bshould work when the workflow's required state is designed correctly.
This test catches accidental use of:
static Dictionary<string, object>or other process-local continuation storage.
For durable state, use a shared test store.
Use the MCP Conformance Framework
Application-specific tests verify your own contract.
The MCP Conformance Test Framework verifies protocol behavior against the MCP specification. It supports both server and client testing and includes wire-schema validation for JSON-RPC messages.
For a server, the framework can connect to the running endpoint and execute scenarios such as:
tools-list
tools-call
resources
promptsThe available scenarios evolve with the specification and test framework.
A typical server invocation is:
npx @modelcontextprotocol/conformance \
server \
--url http://localhost:3000/mcpThe framework can also run specific scenarios or suites.
Conformance Tests Are Not Business Tests
Do not assume:
Conformance passedmeans:
Application is production readyConformance primarily answers:
Does the implementation behave according to MCP protocol requirements?Your contract suite answers:
Does our particular tool behave as our clients expect?Both are valuable.
Add Conformance to CI
A production pipeline can look like:
Pull Request
↓
Build
↓
Unit Tests
↓
Contract Tests
↓
Integration Tests
↓
MCP Conformance
↓
Security Tests
↓
DeployThe conformance framework provides a GitHub Action that can run server or client tests in CI.
For example, the framework documents a server-side action pattern:
steps:
- uses: actions/checkout@v4
- run: |
my-server --port 3001 &
- uses: modelcontextprotocol/[email protected]
with:
mode: server
url: http://localhost:3001/mcpThe exact action version should be pinned according to the version approved by your project.
Manage Expected Failures Carefully
The conformance framework supports an expected-failures baseline.
This can be useful during incremental adoption:
Known failures:
scenario-a
scenario-bBut an expected-failure file should not become a permanent hiding place for regressions.
Use a process:
Known failure
↓
Document reason
↓
Assign owner
↓
Track issue
↓
Fix
↓
Remove baseline entryOtherwise, the test suite can appear green while important protocol behavior remains broken.
Test Multiple Protocol Versions
MCP 2.0 introduces a new 2026-07-28 protocol revision while maintaining interoperability with earlier protocol revisions in supported scenarios. The C# SDK documents automatic negotiation and compatibility behavior.
If your deployment must support multiple client generations, test:
New client → New server
Old client → New server
New client → Old serverDo not assume that compilation compatibility means wire compatibility.
Test the Actual Deployment Configuration
A local test might use:
Stateless = truewhile production accidentally uses:
Stateless = falseor the reverse.
Test configuration that matches production.
The C# SDK's current HTTP transport defaults to stateless mode, while stateful mode can still be explicitly enabled when required.
Detect Contract Drift in CI
A useful CI strategy is:
Tool contract
↓
Contract tests
↓
Pull request
↓
Failure if breaking changeFor example, a pull request that changes:
get_order_statusto:
getOrderStatusshould fail.
Similarly, removing:
orderIdfrom the required schema should fail if clients depend on it.
Use Consumer-Driven Contracts When Appropriate
If several independent clients consume the same MCP server, consider consumer-driven contract testing.
For example:
MCP Server
|
+── Agent A
+── Agent B
+── Internal ApplicationEach consumer can define the subset of the contract it requires.
This is useful when one MCP server serves multiple teams.
The goal is not to freeze every implementation detail.
The goal is to protect behavior that consumers actually depend on.
Common Mistakes
Testing Only the C# Method
The MCP protocol surface can change even when the method works.
Comparing Entire JSON Schemas
This creates brittle tests when irrelevant serialization details change.
Ignoring Tool Names
Tool names are part of the client-facing contract.
Testing Only Happy Paths
AI-generated inputs are not guaranteed to be valid.
Skipping Authorization Tests
A tool that works correctly for an authorized user can still have a tenant-isolation vulnerability.
Depending on In-Memory State
Stateless HTTP should not accidentally depend on one server process.
Treating Conformance as Business Testing
Protocol compliance does not prove business correctness.
Keeping Permanent Expected Failures
Known failures should be temporary and tracked.
Testing Only One Protocol Version
Compatibility bugs frequently appear at protocol boundaries.
Overusing End-to-End Tests
Full E2E tests are slower and harder to diagnose.
Use the lowest test level that can verify the behavior.
Troubleshooting
Tool Discovery Test Fails
Check:
Tool registration
Tool name
Server startup
Transport
Protocol negotiationSchema Test Fails After an SDK Upgrade
Determine whether:
Your contract changedor:
Only schema serialization changedAvoid blindly updating the test.
HTTP Test Passes Locally but Fails in CI
Check:
Base URL
Port
TLS
Authentication
Environment variables
Server startup timingStateless Test Fails Across Instances
Look for process-local state:
static fields
IMemoryCache
in-memory dictionaries
session objectsMove required shared state to an appropriate external store.
Conformance Fails but Contract Tests Pass
Your application-specific contract may still work while the protocol implementation violates an MCP requirement.
Inspect the conformance scenario and wire-schema failure.
Contract Test Passes but Agent Fails
Your test may be too narrow.
Add an E2E test that exercises:
Agent
↓
MCP Client
↓
MCP Server
↓
Tool
↓
DependencyRecommended Test Pyramid
A practical MCP testing strategy is:
E2E
/ \
Conformance
/ \
Integration
/ \
Contract Tests
/ \
Unit TestsThe approximate distribution should favor fast tests.
For example:
Many unit tests
Many contract tests
Moderate integration tests
Targeted conformance tests
Few critical E2E testsThe exact numbers should be determined by application complexity and risk.
Example Test Matrix
| Area | Unit | Contract | Integration | Conformance | E2E |
|---|---|---|---|---|---|
| Tool logic | Yes | No | No | No | Sometimes |
| Tool discovery | No | Yes | Yes | Yes | Sometimes |
| Input schema | No | Yes | Yes | Yes | No |
| Authorization | Yes | Yes | Yes | Auth scenarios | Yes |
| Header consistency | No | No | Yes | Yes | No |
| Stateless behavior | No | No | Yes | Yes | Sometimes |
| Multi-round requests | Partial | Yes | Yes | Yes | Yes |
| Database failures | Yes | No | Yes | No | Yes |
| Agent workflow | No | No | No | No | Yes |
The purpose of the table is not to prescribe a rigid testing ratio.
It is to prevent important behaviors from being tested at the wrong level.
Best Practices
Treat every important MCP tool as an API contract.
Test tool discovery and names.
Verify required input parameters.
Test valid and invalid inputs.
Test result contracts.
Test meaningful error categories.
Test authentication and authorization.
Test tenant isolation for multi-tenant tools.
Test header/body consistency when using MCP HTTP metadata.
Test stateless behavior across server instances.
Use in-memory transport for fast protocol-level tests where appropriate.
Use real HTTP tests for HTTP-specific behavior.
Use MCP conformance tests for protocol compliance.
Add conformance testing to CI.
Keep expected-failure baselines temporary.
Test supported protocol versions.
Test retries and idempotency for side-effecting tools.
Test cancellation and timeout behavior.
Avoid brittle full-schema comparisons.
Keep E2E tests focused on critical workflows.
Frequently Asked Questions
What is contract testing for an MCP tool?
Contract testing verifies that an MCP tool continues to expose the interface expected by its consumers, including its name, schema, inputs, outputs, and important failure behavior.
Is an MCP tool contract the same as a C# method signature?
No.
The C# signature is only one implementation detail. The MCP contract also includes the externally visible protocol representation and behavior.
Should I use unit tests or integration tests for MCP tools?
Use both.
Unit tests are best for business logic. Contract and integration tests verify the MCP-facing behavior.
What is MCP conformance testing?
MCP conformance testing checks an MCP client or server implementation against protocol requirements. The official MCP Conformance Test Framework captures protocol interactions and performs specification checks, including wire-schema validation.
Can I use the C# SDK's in-memory transport for testing?
Yes. The official C# SDK documents in-memory stream transports as useful for testing servers and clients in the same process without network overhead.
Should I test every possible MCP request?
No.
Prioritize:
Public tools
Critical tools
Security-sensitive tools
Side-effecting tools
Complex workflows
Backward-compatible behaviorShould schemas be tested as complete JSON snapshots?
Usually not.
Prefer targeted assertions for fields that are genuinely part of your contract.
How do I test stateless MCP?
Run the same logical workflow across different server instances or processes and verify that required state is not stored only in process memory.
Should conformance tests replace integration tests?
No.
Conformance validates protocol behavior. Application-specific integration tests validate your own business and operational contract.
How should I test multi-round MCP tools?
Test the complete sequence:
Initial request
↓
Input required
↓
Input response
↓
Continuation
↓
Final resultThen add negative cases such as invalid input, expired state, cancellation, and retry.
Conclusion
An MCP server should be tested like a distributed API, not merely like a collection of C# methods.
A useful testing strategy is:
Business Logic
↓
Tool Contract
↓
MCP Integration
↓
Protocol Conformance
↓
Critical E2E WorkflowContract tests are the layer that connects application code to the interface consumed by MCP clients and AI agents.
They catch changes such as:
Tool renamed
Parameter removed
Schema changed
Authorization weakened
Result structure changed
Error behavior changed
Stateless assumptions brokenThe MCP ecosystem now also provides a formal Conformance Test Framework that validates client and server implementations against the protocol and performs wire-schema checks.
The C# SDK provides additional testing-friendly infrastructure, including in-memory transports that allow MCP clients and servers to communicate without requiring a network deployment.
The most important principle is:
Test the contract your MCP clients consume, not only the C# implementation behind it.
A production-ready MCP test suite should make a contract change visible immediately:
Developer changes tool
↓
Contract test detects change
↓
Integration test verifies wire behavior
↓
Conformance test verifies MCP compliance
↓
CI blocks unintended regressionThat approach makes MCP tools much easier to evolve safely as the protocol, SDK, clients, and AI-agent workflows continue to change.
Join the conversation! Your thoughts help the community grow.