diff --git a/src/NATS.Server/Auth/Jwt/AccountResolver.cs b/src/NATS.Server/Auth/Jwt/AccountResolver.cs
new file mode 100644
index 0000000..b3739b2
--- /dev/null
+++ b/src/NATS.Server/Auth/Jwt/AccountResolver.cs
@@ -0,0 +1,65 @@
+using System.Collections.Concurrent;
+
+namespace NATS.Server.Auth.Jwt;
+
+///
+/// Resolves account JWTs by account NKey public key. The server calls
+/// during client authentication to obtain the
+/// account JWT that was previously published by an account operator.
+///
+///
+/// Reference: golang/nats-server/server/accounts.go:4035+ — AccountResolver interface
+/// and MemAccResolver implementation.
+///
+public interface IAccountResolver
+{
+ ///
+ /// Fetches the JWT for the given account NKey. Returns null when
+ /// the NKey is not known to this resolver.
+ ///
+ Task FetchAsync(string accountNkey);
+
+ ///
+ /// Stores (or replaces) the JWT for the given account NKey. Callers that
+ /// target a read-only resolver should check first.
+ ///
+ Task StoreAsync(string accountNkey, string jwt);
+
+ ///
+ /// When true, is not supported and will
+ /// throw . Directory and URL resolvers
+ /// may be read-only; in-memory resolvers are not.
+ ///
+ bool IsReadOnly { get; }
+}
+
+///
+/// In-memory account resolver backed by a .
+/// Suitable for tests and simple single-operator deployments where account JWTs
+/// are provided at startup via .
+///
+///
+/// Reference: golang/nats-server/server/accounts.go — MemAccResolver
+///
+public sealed class MemAccountResolver : IAccountResolver
+{
+ private readonly ConcurrentDictionary _accounts =
+ new(StringComparer.Ordinal);
+
+ ///
+ public bool IsReadOnly => false;
+
+ ///
+ public Task FetchAsync(string accountNkey)
+ {
+ _accounts.TryGetValue(accountNkey, out var jwt);
+ return Task.FromResult(jwt);
+ }
+
+ ///
+ public Task StoreAsync(string accountNkey, string jwt)
+ {
+ _accounts[accountNkey] = jwt;
+ return Task.CompletedTask;
+ }
+}
diff --git a/tests/NATS.Server.Tests/AccountResolverTests.cs b/tests/NATS.Server.Tests/AccountResolverTests.cs
new file mode 100644
index 0000000..691148e
--- /dev/null
+++ b/tests/NATS.Server.Tests/AccountResolverTests.cs
@@ -0,0 +1,68 @@
+using NATS.Server.Auth.Jwt;
+
+namespace NATS.Server.Tests;
+
+public class AccountResolverTests
+{
+ [Fact]
+ public async Task Store_and_fetch_roundtrip()
+ {
+ var resolver = new MemAccountResolver();
+ const string nkey = "AABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQ";
+ const string jwt = "eyJhbGciOiJlZDI1NTE5LW5rZXkiLCJ0eXAiOiJKV1QifQ.payload.sig";
+
+ await resolver.StoreAsync(nkey, jwt);
+ var fetched = await resolver.FetchAsync(nkey);
+
+ fetched.ShouldBe(jwt);
+ }
+
+ [Fact]
+ public async Task Fetch_unknown_key_returns_null()
+ {
+ var resolver = new MemAccountResolver();
+
+ var result = await resolver.FetchAsync("UNKNOWN_NKEY");
+
+ result.ShouldBeNull();
+ }
+
+ [Fact]
+ public async Task Store_overwrites_existing_entry()
+ {
+ var resolver = new MemAccountResolver();
+ const string nkey = "AABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQ";
+ const string originalJwt = "original.jwt.token";
+ const string updatedJwt = "updated.jwt.token";
+
+ await resolver.StoreAsync(nkey, originalJwt);
+ await resolver.StoreAsync(nkey, updatedJwt);
+ var fetched = await resolver.FetchAsync(nkey);
+
+ fetched.ShouldBe(updatedJwt);
+ }
+
+ [Fact]
+ public void IsReadOnly_returns_false()
+ {
+ IAccountResolver resolver = new MemAccountResolver();
+
+ resolver.IsReadOnly.ShouldBeFalse();
+ }
+
+ [Fact]
+ public async Task Multiple_accounts_are_stored_independently()
+ {
+ var resolver = new MemAccountResolver();
+ const string nkey1 = "AABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQ1";
+ const string nkey2 = "AABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQ2";
+ const string jwt1 = "jwt.for.account.one";
+ const string jwt2 = "jwt.for.account.two";
+
+ await resolver.StoreAsync(nkey1, jwt1);
+ await resolver.StoreAsync(nkey2, jwt2);
+
+ (await resolver.FetchAsync(nkey1)).ShouldBe(jwt1);
+ (await resolver.FetchAsync(nkey2)).ShouldBe(jwt2);
+ }
+}